還在一個個寫規則?來了解下爬蟲的智能化解析吧!

爬蟲是作什麼的?是幫助咱們來快速獲取有效信息的。然而作過爬蟲的人都知道,解析是個麻煩事。javascript

好比一篇新聞吧,連接是這個:https://news.ifeng.com/c/7kQcQG2peWU,頁面預覽圖以下:html

圖片

預覽圖java

咱們須要從頁面中提取出標題、發佈人、發佈時間、發佈內容、圖片等內容。通常狀況下咱們須要怎麼辦?寫規則。python

那麼規則都有什麼呢?懟正則,懟 CSS 選擇器,懟 XPath。咱們須要對標題、發佈時間、來源等內容作規則匹配,更有甚者再須要正則表達式來輔助一下。咱們可能就須要用 re、BeautifulSoup、pyquery 等庫來實現內容的提取和解析。git

但若是咱們有成千上萬個不一樣樣式的頁面怎麼辦呢?它們來自成千上萬個站點,難道咱們還須要對他們一一寫規則來匹配嗎?這得要多大的工做量啊。另外這些萬一弄很差還會解析有問題。好比正則表達式在某些狀況下匹配不了了,CSS、XPath 選擇器選錯位了也會出現問題。github

想必你們可能見過如今的瀏覽器有閱讀模式,好比咱們把這個頁面用 Safari 瀏覽器打開,而後開啓閱讀模式,看看什麼效果:web

圖片

Safari預覽正則表達式

頁面一會兒變得很是清爽,只保留了標題和須要讀的內容。原先頁面多餘的導航欄、側欄、評論等等的通通都被去除了。它怎麼作到的?難道是有人在裏面寫好規則了?那固然不可能的事。其實,這裏面就用到了智能化解析了。算法

那麼本篇文章,咱們就來了解一下頁面的智能化解析的相關知識。json

智能化解析

所謂爬蟲的智能化解析,顧名思義就是再也不須要咱們針對某一些頁面來專門寫提取規則了,咱們能夠利用一些算法來計算出來頁面特定元素的位置和提取路徑。好比一個頁面中的一篇文章,咱們能夠經過算法計算出來,它的標題應該是什麼,正文應該是哪部分區域,發佈時間是什麼等等。

其實智能化解析是很是難的一項任務,好比說你給人看一個網頁的一篇文章,人能夠迅速找到這篇文章的標題是什麼,發佈時間是什麼,正文是哪一塊,或者哪一塊是廣告位,哪一塊是導航欄。但給機器來識別的話,它面臨的是什麼?僅僅是一系列的 HTML 代碼而已。那究竟機器是怎麼作到智能化提取的呢?其實這裏面融合了多方面的信息。

  • 好比標題。通常它的字號是比較大的,並且長度不長,位置通常都在頁面上方,並且大部分狀況下它應該和 title 標籤裏的內容是一致的。

  • 好比正文。它的內容通常是最多的,並且會包含多個段落 p 或者圖片 img 標籤,另外它的寬度通常可能會佔用到頁面的三分之二區域,而且密度(字數除以標籤數量)會比較大。

  • 好比時間。不一樣語言的頁面可能不一樣,但時間的格式是有限的,如 2019-02-20 或者 2019/02/20 等等,也有的多是美式的記法,順序不一樣,這些也有特定的模式能夠識別。

  • 好比廣告。它的標籤通常可能會帶有 ads 這樣的字樣,另外大多數可能會處於文章底部、頁面側欄,並可能包含一些特定的外鏈內容。

另外還有一些特色就再也不一一贅述了,這其中包含了區塊位置、區塊大小、區塊標籤、區塊內容、區塊疏密度等等多種特徵,另外不少狀況下還須要藉助於視覺的特徵,因此說這裏面其實結合了算法計算、視覺處理、天然語言處理等各個方面的內容。若是能把這些特徵綜合運用起來,再通過大量的數據訓練,是能夠獲得一個很是不錯的效果的。

業界進展

將來的話,頁面也會愈來愈多,頁面的渲染方式也會發生很大的變化,爬蟲也會愈來愈難作,智能化爬蟲也將會變得愈來愈重要。

目前工業界,其實已經有落地的算法應用了。通過個人一番調研,目前發現有這麼幾種算法或者服務對頁面的智能化解析作的比較好:

  • Diffbot,國外的一家專門來作智能化解析服務的公司,https://www.diffbot.com

  • Boilerpipe,Java 語言編寫的一個頁面解析算法,https://github.com/kohlschutter/boilerpipe

  • Embedly,提供頁面解析服務的公司,https://embed.ly/extract

  • Readability,是一個頁面解析算法,但如今官方的服務已經關閉了,https://www.readability.com/

  • Mercury,Readability 的替代品,https://mercury.postlight.com/

  • Goose,Java 語音編寫的頁面解析算法,https://github.com/GravityLabs/goose

那麼這幾種算法或者服務到底哪些好呢,Driffbot 官方曾作過一個對比評測,使用 Google 新聞的一些文章,使用不一樣的算法依次摘出其中的標題和文本,而後與真實標註的內容進行比較,比較的指標就是文字的準確率和召回率,以及根據兩者計算出的 F1 分數。

其結果對好比下:

Service/Software Precision Recall F1-Score

Diffbot

0.968

0.978

0.971

Boilerpipe

0.893

0.924

0.893

Readability

0.819

0.911

0.854

AlchemyAPI

0.876

0.892

0.850

Embedly

0.786

0.880

0.822

Goose

0.498

0.815

0.608

通過對比咱們能夠發現,Diffbot 的準確率和召回率都獨佔鰲頭,其中的 F1 值達到了 0.97,能夠說準確率很是高了。另外接下來比較厲害的就是 Boilerpipe 和 Readability,Goose 的表現則很是差,F1 跟其餘的算法差了一大截。下面是幾個算法的 F1 分數對比狀況:image.png

F1分數對比

有人可能好奇爲何 Diffbot 這麼厲害?我也查詢了一番。Diffbot 自 2010 年以來就致力於提取 Web 頁面數據,並提供許多 API 來自動解析各類頁面。其中他們的算法依賴於天然語言技術、機器學習、計算機視覺、標記檢查等多種算法,而且全部的頁面都會考慮到當前頁面的樣式以及可視化佈局,另外還會分析其中包含的圖像內容、CSS 甚至 Ajax 請求。另外在計算一個區塊的置信度時還考慮到了和其餘區塊的關聯關係,基於周圍的標記來計算每一個區塊的置信度。

總之,Diffbot 也是一直致力於這一方面的服務,整個 Diffbot 就是頁面解析起家的,如今也一直專一於頁面解析服務,準確率高也就不足爲怪了。

但它們的算法開源了嗎?很遺憾,並無,並且我也沒有找到相關的論文介紹它們本身的具體算法。

因此,若是想實現這麼好的效果,那就使用它們家的服務就行了。

接下來的內容,咱們就來講說如何使用 Diffbot 來進行頁面的智能解析。另外還有 Readability 算法也很是值得研究,我會寫專門的文章來介紹 Readability 及其與 Python 的對接使用。

Diffbot 頁面解析

首先咱們須要註冊一個帳號,它有 15 天的免費試用,註冊以後會得到一個 Developer Token,這就是使用 Diffbot 接口服務的憑證。

接下來切換到它的測試頁面中,連接爲:https://www.diffbot.com/dev/home/,咱們來測試一下它的解析效果究竟是怎樣的。

這裏咱們選擇的測試頁面就是上文所述的頁面,連接爲:https://news.ifeng.com/c/7kQcQG2peWU,API 類型選擇 Article API,而後點擊 Test Drive 按鈕,接下來它就會出現當前頁面的解析結果:

圖片

結果

這時候咱們能夠看到,它幫咱們提取出來了標題、發佈時間、發佈機構、發佈機構連接、正文內容等等各類結果。並且目前來看都十分正確,時間也自動識別以後作了轉碼,是一個標準的時間格式。

接下來咱們繼續下滑,查看還有什麼其餘的字段,這裏咱們還能夠看到有 html 字段,它和 text 不一樣的是,它包含了文章內容的真實 HTML 代碼,所以圖片也會包含在裏面,如圖所示:

圖片

結果

另外最後面還有 images 字段,他以列表形式返回了文章套圖及每一張圖的連接,另外還有文章的站點名稱、頁面所用語言等等結果,如圖所示:

圖片

結果

固然咱們也能夠選擇 JSON 格式的返回結果,其內容會更加豐富,例如圖片還返回了其寬度、高度、圖片描述等等內容,另外還有各類其餘的結果如麪包屑導航等等結果,如圖所示:

圖片

結果

通過手工覈對,發現其返回的結果都是徹底正確的,準確率至關之高!

因此說,若是你對準確率要求沒有那麼很是很是嚴苛的狀況下,使用 Diffbot 的服務能夠幫助咱們快速地提取頁面中所需的結果,省去了咱們絕大多數的手工勞動,能夠說是很是讚了。

可是,咱們也不能總在網頁上這麼試吧。其實 Diffbot 也提供了官方的 API 文檔,讓咱們來一探究竟。

Diffbot API

Driffbot 提供了多種 API,如 Analyze API、Article API、Disscussion API 等。

下面咱們以 Article API 爲例來講明一下它的用法,其官方文檔地址爲:https://www.diffbot.com/dev/docs/article/,API 調用地址爲:

 
 

https://api.diffbot.com/v3/article

咱們能夠用 GET 方式來進行請求,其中的 Token 和 URL 均可以以參數形式傳遞給這個 API,其必備的參數有:

  • token:即 Developer Token

  • url:即要解析的 URL 連接

另外它還有幾個可選參數:

  • fields:用來指定返回哪些字段,默認已經有了一些固定字段,這個參數能夠指定還能夠額外返回哪些可選字段

  • paging:若是是多頁文章的話,若是將這個參數設置爲 false 則能夠禁止多頁內容拼接

  • maxTags:能夠設置返回的 Tag 最大數量,默認是 10 個

  • tagConfidence:設置置信度的閾值,超過這個值的 Tag 纔會被返回,默認是 0.5

  • discussion:若是將這個參數設置爲 false,那麼就不會解析評論內容

  • timeout:在解析的時候等待的最長時間,默認是 30 秒

  • callback:爲 JSONP 類型的請求而設計的回調

這裏你們可能關注的就是 fields 字段了,在這裏我專門作了一下梳理,首先是一些固定字段:

  • type:文本的類型,這裏就是 article 了

  • title:文章的標題

  • text:文章的純文本內容,若是是分段內容,那麼其中會以換行符來分隔

  • html:提取結果的 HTML 內容

  • date:文章的發佈時間,其格式爲 RFC 1123

  • estimatedDate:若是日期時間不太明確,會返回一個預估的時間,若是文章超過兩天或者沒有發佈日期,那麼這個字段就不會返回

  • author:做者

  • authorUrl:做者的連接

  • discussion:評論內容,和 Disscussion API 返回結果同樣

  • humanLanguage:語言類型,如英文仍是中文等

  • numPages:若是文章是多頁的,這個參數會控制最大的翻頁拼接數目

  • nextPages:若是文章是多頁的,這個參數能夠指定文章後續連接

  • siteName:站點名稱

  • publisherRegion:文章發佈地區

  • publisherCountry:文章發佈國家

  • pageUrl:文章連接

  • resolvedPageUrl:若是文章是從 pageUrl 重定向過來的,則返回此內容

  • tags:文章的標籤或者文章包含的實體,根據天然語言處理技術和 DBpedia 計算生成,是一個列表,裏面又包含了子字段:

  • label:標籤名

  • count:標籤出現的次數

  • score:標籤置信度

  • rdfTypes:若是實體能夠由多個資源表示,那麼則返回相關的 URL

  • type:類型

  • uri:Diffbot Knowledge Graph 中的實體連接

  • images:文章中包含的圖片

  • videos:文章中包含的視頻

  • breadcrumb:麪包屑導航信息

  • diffbotUri:Diffbot 內部的 URL 連接

以上的預約字段就是若是能夠返回那就會返回的字段,是不能定製化配置的,另外咱們還能夠經過 fields 參數來指定擴展以下可選字段:

  • quotes:引用信息

  • sentiment:文章的情感值,-1 到 1 之間

  • links:全部超連接的頂級連接

  • querystring:請求的參數列表

好,以上即是這個 API 的用法,你們能夠申請以後使用這個 API 來作智能化解析了。

下面咱們用一個實例來看一下這個 API 的用法,代碼以下:

 
 

import requests, json

url = 'https://api.diffbot.com/v3/article'
params = {
    'token''77b41f6fbb24495113d52836528fa',
    'url''https://news.ifeng.com/c/7kQcQG2peWU',
    'fields''meta' 
}
response = requests.get(url, params=params)
print(json.dumps(response.json(), indent=2, ensure_ascii=False))

這裏首先定義了 API 的連接,而後指定了 params 參數,即 GET 請求參數。

參數中包含了必選的 token、url 字段,也設置了可選的 fields 字段,其中  fields 爲可選的擴展字段 meta 標籤。

咱們來看下運行結果,結果以下:

 
 

{
  "request": {
    "pageUrl""https://news.ifeng.com/c/7kQcQG2peWU",
    "api""article",
    "fields""sentiment, meta",
    "version"3
  },
  "objects": [
    {
      "date""Wed, 20 Feb 2019 02:26:00 GMT",
      "images": [
        {
          "naturalHeight"460,
          "width"640,
          "diffbotUri""image|3|-1139316034",
          "url""http://e0.ifengimg.com/02/2019/0219/1731DC8A29EB2219C7F2773CF9CF319B3503D0A1_size382_w690_h460.png",
          "naturalWidth"690,
          "primary"true,
          "height"426
        },
        // ...
      ],
      "author""中國新聞網",
      "estimatedDate""Wed, 20 Feb 2019 06:47:52 GMT",
      "diffbotUri""article|3|1591137208",
      "siteName""ifeng.com",
      "type""article",
      "title""故宮,你低調點!故宮:不,實力已不容許我繼續低調",
      "breadcrumb": [
        {
          "link""https://news.ifeng.com/",
          "name""資訊"
        },
        {
          "link""https://news.ifeng.com/shanklist/3-35197-/",
          "name""大陸"
        }
      ],
      "humanLanguage""zh",
      "meta": {
        "og": {
          "og:time ""2019-02-20 02:26:00",
          "og:image""https://e0.ifengimg.com/02/2019/0219/1731DC8A29EB2219C7F2773CF9CF319B3503D0A1_size382_w690_h460.png",
          "og:category ""鳳凰資訊",
          "og: webtype""news",
          "og:title""故宮,你低調點!故宮:不,實力已不容許我繼續低調",
          "og:url""https://news.ifeng.com/c/7kQcQG2peWU",
          "og:description""  「個人名字叫紫禁城,快要600歲了,這上元的夜啊,老是讓我沉醉,這麼久了卻從未中止。」   「重"
        },
        "referrer""always",
        "description""  「個人名字叫紫禁城,快要600歲了,這上元的夜啊,老是讓我沉醉,這麼久了卻從未中止。」   「重",
        "keywords""故宮 紫禁城 故宮博物院 燈光 元宵節 博物館 一票難求 元之 中新社 午門 杜洋 藏品 文化 皇帝 清明上河圖 元宵 千里江山圖卷 中英北京條約 中法北京條約 天津條約",
        "title""故宮,你低調點!故宮:不,實力已不容許我繼續低調_鳳凰資訊"
      },
      "authorUrl""https://feng.ifeng.com/author/308904",
      "pageUrl""https://news.ifeng.com/c/7kQcQG2peWU",
      "html""<p>&ldquo;個人名字叫紫禁城,快要600歲了,這上元的夜啊,老是讓我沉醉,這麼久了卻從未中止。...</blockquote> </blockquote>",
      "text""「個人名字叫紫禁城,快要600歲了,這上元的夜啊,老是讓我沉醉,這麼久了卻從未中止。」\n「...",
      "authors": [
        {
          "name""中國新聞網",
          "link""https://feng.ifeng.com/author/308904"
        }
      ]
    }
  ]
}

可見其返回瞭如上的內容,是一個完整的 JSON 格式,其中包含了標題、正文、發佈時間等等各類內容。

可見,不須要咱們配置任何提取規則,咱們就能夠完成頁面的分析和抓取,得來全不費功夫。

Diffbot SDK

另外 Diffbot 還提供了幾乎全部語言的 SDK 支持,咱們也可使用 SDK 來實現如上功能,連接爲:https://www.diffbot.com/dev/docs/libraries/,若是你們使用  Python 的話,能夠直接使用 Python 的 SDK 便可,Python 的 SDK 連接爲:https://github.com/diffbot/diffbot-python-client。

這個庫並無發佈到 PyPi,須要本身下載並導入使用,另外這個庫是使用 Python 2 寫的,其實本質上就是調用了 requests 庫,若是你們感興趣的話能夠看一下。

下面是一個調用示例:

 
 

from client import DiffbotClient,DiffbotCrawl

diffbot = DiffbotClient()
token = 'your_token'
url = 'http://shichuan.github.io/javascript-patterns/'
api = 'article'
response = diffbot.request(url, token, api)

經過這行代碼咱們就能夠經過調用 Article API 來分析咱們想要的 URL 連接了,返回結果是相似的。

具體的用法你們直接看下它的源碼註釋就一目瞭然了,仍是很清楚的。

好,以上即是對智能化提取頁面原理的基本介紹以及對 Diffbot 的用法的講解,後面我會繼續介紹其餘的智能化解析方法以及一些相關實戰,但願你們能夠多多關注。

相關文章
相關標籤/搜索