1. 程式人生 > 實用技巧 >釋出一個智慧解析庫 Gerapy Auto Extractor

釋出一個智慧解析庫 Gerapy Auto Extractor

演算法

整個演算法的實現比較雜,我看了幾篇論文和幾個專案的原始碼,然後經過一些修改實現的。

其中列表頁解析的參考論文:

詳情頁解析的參考論文和專案:

這些都是不完全參考,然後加上自己的一些修改最終才形成了現在的結果。

演算法在這裡就幾句話描述一下思路,暫時先不展開講了。

列表頁解析:

  • 找到具有公共父節點的連續相鄰子節點,父節點作為候選節點。
  • 根據節點特徵進行聚類融合,將符合條件的父節點融合在一起。
  • 根據節點的特徵、文字密度、視覺資訊(尚未實現)挑選最優父節點。
  • 從最優父節點內根據標題特徵提取標題。

詳情頁解析:

  • 標題根據 meta、title、h 節點綜合提取
  • 時間根據 meta、正則資訊綜合提取
  • 正文根據文字密度、符號密度、視覺資訊(尚未實現)綜合提取。

後面等完善了之後再詳細介紹演算法的具體實現,現在如感興趣可以去看原始碼。

釋出一個智慧解析庫 Gerapy Auto Extractor

崔慶才丨靜覓 微軟(中國)有限公司 軟體工程師

之前我寫過幾篇文章介紹過有關爬蟲的智慧解析演算法,包括商業化應用 Diffbot、Readability、Newspaper 這些庫,另外我有一位朋友之前還專門針對新聞正文的提取演算法 GeneralNewsExtractor,這段時間我也參考和研究了一下這些庫的演算法,同時參考一些論文,也寫了一個智慧解析庫,在這裡就做一個非正式的介紹。

引入

那首先說說我想做的是什麼。

比如這裡有一個網站,網易新聞,https://news.163.com/rank/,這裡有個新聞列表,預覽圖如下

任意點開一篇新聞,看到的結果如下:

(二維碼自動識別)

我現在需要做到的是在不編寫任何 XPath、Selector 的情況下實現下面資訊的提取:

對於列表頁來說,我要提取新聞的所有標題列表和對應的連結,它們就是圖中的紅色區域:

這裡紅色區域分了多個區塊,比如這裡一共就是 40 個連結,我都需要提取出來,包括標題的名稱,標題的 URL。

我們看到頁面裡面還有很多無用的連結,如上圖綠色區域,包括分類、內部導航等,這些需要排除掉。

對於詳情頁,我主要關心的內容有標題、釋出時間、正文內容,它們就是圖中紅色區域:

其中這裡也帶有一些干擾項,比如綠色區域的側邊欄的內容,無用的分享連結等。

總之,我想實現某種演算法,實現如上兩大部分的智慧化提取。

框架

之前我開發了一個叫做 Gerapy的框架,是一個基於 Scrapy、Scrapyd 的分散式爬蟲管理框架,屬 1.x 版本。現在正在開發 Gerapy 2.x 版本,其定位轉向了 Scrapy 的視覺化配置和除錯、智慧化解析方向,放棄支援 Scraypd,轉而支援 Docker、Kubernetes 的部署和監控。

對於智慧解析來說,就像剛才說的,我期望的就是上述的功能,在不編寫任何 XPath 和 Selector 的情況下實現頁面關鍵內容的提取。

框架現在釋出了第一個初步版本,名稱叫做 Gerapy Auto Extractor,名字 Gerapy 相關,也會作為 Gerapy 的其中一個模組。

GitHub 連結:

現在已經發布了 PyPi,https://pypi.org/project/gerapy-auto-extractor/,可以使用pip3 來安裝,安裝方式如下:

pip3 install gerapy-auto-extractor

安裝完了之後我們就可以匯入使用了。

功能

下面簡單介紹下它的功能,它能夠做到列表頁和詳情頁的解析。

列表頁:

  • 標題內容
  • 標題連結

詳情頁:

  • 標題
  • 正文
  • 釋出時間

先暫時實現瞭如上內容的提取,其他欄位的提取暫時還未實現。

使用

要使用 Gerapy Auto Extractor,前提我們必須要先獲得 HTML 程式碼,注意這個 HTML 程式碼是我們在瀏覽器裡面看到的內容,是整個頁面渲染完成之後的程式碼。在某些情況下如果我們簡單用「檢視原始碼」或 requests 請求獲取到的原始碼並不是真正渲染完成後的 HTML 程式碼。

要獲取完整 HTML 程式碼可以在瀏覽器開發者工具,開啟 Elements 選項卡,然後複製你所看到的 HTML 內容即可。

先測試下列表頁,比如我把這個儲存為 list.html,

然後編寫提取程式碼如下:

import json
from gerapy_auto_extractor.extractors.list import extract_list

html = open('list.html', encoding='utf-8').read()
print(json.dumps(extract_list(html), indent=2, ensure_ascii=False, default=str))

就是這麼簡單,核心程式碼就一行,就是呼叫了一個 extract_list 方法。

執行結果如下:

[
  {
    "title": "1家6口5年"結離婚"10次:兒媳"嫁"公公嶽",
    "url": "https://news.163.com/20/0705/05/FGOFE1HJ0001875P.html"
  },
  {
    "title": ""港獨"議員潑水阻礙教科書議題林鄭月娥深夜斥責",
    "url": "https://news.163.com/20/0705/02/FGO66FU90001899O.html"
  },
  {
    "title": "感動中國致敬留德女學生:街頭怒懟"港獨"有理有",
    "url": "https://news.163.com/20/0705/08/FGOPG3AM0001899O.html"
  },
  {
    "title": "香港名醫諷刺港警流血少過月經受訪時辯稱遭盜號",
    "url": "https://news.163.com/20/0705/01/FGO42EK90001875O.html"
  },
  {
    "title": "李晨獨居北京複式豪宅沒想到肌肉男喜歡小花椅子",
    "url": "https://home.163.com/20/0705/07/FGOLER1200108GL2.html"
  },
  {
    "title": "不戰東京!林丹官宣退役正式結束20年職業生涯",
    "url": "https://sports.163.com/20/0704/12/FGML920300058782.html"
  },
  {
    "title": "香港美女搬運工月薪1.6萬每月花6千租5平出租",
    "url": "https://home.163.com/20/0705/07/FGOLEL1100108GL2.html"
  },
  {
    "title": "杭州第一大P2P"涼了":近百億未還!被警方立案",
    "url": "https://money.163.com/20/0705/07/FGON5T7B00259DLP.html"
  },
  ...
]

可以看到想要的內容就提取出來了,結果是一個列表,包含標題內容和標題連結兩個欄位,由於內容過長,這裡就省略了一部分。

接著我們再測試下正文的提取,隨便開啟一篇文章,比如https://news.ifeng.com/c/7xrdz0kysde,儲存下HTML,命名為 detail.html。

編寫測試程式碼如下:

import json
from gerapy_auto_extractor.extractors import extract_detail
html = open('detail.html', encoding='utf-8').read()
print(json.dumps(extract_detail(html), indent=2, ensure_ascii=False, default=str))

執行結果如下:

{
  "title": "內蒙古巴彥淖爾釋出鼠疫疫情Ⅲ級預警",
  "datetime": "2020-07-05 18:54:15",
  "content": "2020年7月4日,烏拉特中旗人民醫院報告了1例疑似腺鼠疫病例,根據《內蒙古自治區鼠疫疫情預警實施方案》(內鼠防應急發﹝2020﹞7號)和《自治區鼠疫控制應急預案(2020年版)》(內政辦發﹝2020﹞17號)的要求,經研究決定,於7月5日釋出鼠疫防控Ⅲ級預警資訊如下:n一、預警級別及起始時間n預警級別:Ⅲ級。n2020年7月5日起進入預警期,預警時間從本預警通告發布之日持續到2020年底。n二、注意事項n當前我市存在人間鼠疫疫情傳播的風險,請廣大公眾嚴格按照鼠疫防控“三不三報”的要求,切實做好個人防護,提高自我防護意識和能力。不私自捕獵疫源動物、不剝食疫源動物、不私自攜帶疫源動物及其產品出疫區;發現病(死)旱獺及其他動物要報告、發現疑似鼠疫病人要報告、發現不明原因的高熱病人和急死病人要報告。要謹慎進入鼠疫疫源地,如有鼠疫疫源地的旅居史,出現發熱等不適症狀時及時赴定點醫院就診。n按照國家、自治區鼠疫控制應急預案的要求,市衛生健康委將根據鼠疫疫情預警的分級,及時釋出和調整預警資訊。n巴彥淖爾市衛生健康委員會n2020年7月5日n來源:巴彥淖爾市衛生健康委員會"
}

成功輸出了標題、正文、釋出時間等內容。

這裡就演示了基本的列表頁、詳情頁的提取操作。

演算法

整個演算法的實現比較雜,我看了幾篇論文和幾個專案的原始碼,然後經過一些修改實現的。

其中列表頁解析的參考論文:

詳情頁解析的參考論文和專案:

這些都是不完全參考,然後加上自己的一些修改最終才形成了現在的結果。

演算法在這裡就幾句話描述一下思路,暫時先不展開講了。

列表頁解析:

  • 找到具有公共父節點的連續相鄰子節點,父節點作為候選節點。
  • 根據節點特徵進行聚類融合,將符合條件的父節點融合在一起。
  • 根據節點的特徵、文字密度、視覺資訊(尚未實現)挑選最優父節點。
  • 從最優父節點內根據標題特徵提取標題。

詳情頁解析:

  • 標題根據 meta、title、h 節點綜合提取
  • 時間根據 meta、正則資訊綜合提取
  • 正文根據文字密度、符號密度、視覺資訊(尚未實現)綜合提取。

後面等完善了之後再詳細介紹演算法的具體實現,現在如感興趣可以去看原始碼。

說明

本框架僅僅釋出了最初測試版本,測試覆蓋度比較少,目前僅僅測試了有限的幾個網站,尚未大規模測試和新增對比實驗,因此準確率現在還沒有標準的保證。

參考:關於詳情頁正文的提取我主要參考了GeneralNewsExtractor這個專案,原專案據測試可以達到 90% 以上的準確率。

列表頁我測試了騰訊、網易、知乎等都是可以順利提取的,如:

後面會有大規模測試和修正。

專案初版,肯定存在很多不足,希望大家可以多發 Issue 和提 PR。

另外這裡建立了一個 Gerapy 開發交流群,之前在 QQ 群的也歡迎加入,以後交流就在微信群了,大家在使用過程遇到關於 Gerapy、Gerapy Auto Extractor 的問題歡迎交流。

這裡放一個臨時二維碼,後期可能會失效,失效後大家可以到公眾號「進擊的Coder」獲取加群方式。

待開發功能

  • 視覺資訊的融合
  • 文字相似度的融合
  • 分類模型的融合
  • 下一頁翻頁的資訊提取
  • 正文圖片、視訊的提取
  • 對接 Gerapy

最後感謝大家的支援!

釋出於 07-05