攝影:產品經理
在杭州居然還能吃到豌豆尖,kingname 激動得喝了一碗湯
GNE[1]上線 4 天,已經有不少朋友經過它來編寫本身的新聞類網頁通用爬蟲。html
今天有一個用戶來跟我反饋,GNE 0.1.4 版本在提取澎湃新聞時,只能提取一小部分的內容。git
一開始我覺得是提取算法有問題,Debug 了半天,最後才發現,是新聞正文在預處理的時候,就被提早刪除了!github
爲了解釋這個問題,咱們用一小段 HTML 代碼來還原當時的場景:算法
h = ''' <html> <body> <div class="txt"> 第一行 <p class="con" /> 第二行 <p class="con" /> 第三行 </div> </body> </html> '''
閱讀過 GNE 源代碼的朋友都知道,GNE 會在預處理階段儘量移除沒什麼用的 HTML 標籤。例如上面這段代碼中的兩行<p class="con" />都屬於會干擾提取結果,且對提取沒有任何幫助的標籤。less
因而咱們使用 lxml 庫的方法來移除它:ide
from lxml.html import fromstring selector = fromstring(h) useless_list = selector.xpath('//p[@class="con"]') for useless in useless_list: useless.getparent().remove(useless)
根據想固然的理論:code
找到<p class="con" />標籤
找到它的父標籤
從父標籤裏面把這兩個無效標籤移除掉
整個過程看起來沒有問題,而且預期移除之後的 HTML 應該是這樣的:xml
h = ''' <html> <body> <div class="txt"> 第一行 第二行 第三行 </div> </body> </html> '''
但實際上,現實狀況與想固然的狀況天然不同。真正的輸出結果以下圖所示:htm
<div class="txt">這個標籤下面的text()有三行,分別爲第一行、第二行、第三行。可是使用上面的代碼移除時,第二行與第三行都一併被刪除了。blog
這是由於,這就是ElementTree.remove這個方法的行爲。它不只會移除這個節點,還會移除這個節點父節點的 text()中,位於這個節點後面的全部內容。
因此,正常的作法應該是直接調用要被移除這個節點的.drop_tag()方法。咱們修改一下上面的代碼:
from lxml.html import fromstring from html import unescape from lxml.html import etree h = ''' <html> <body> <div class="txt"> 第一行 <p class="con" /> 第二行 <p class="con" /> 第三行 </div> </body> </html> ''' selector = fromstring(h) useless_list = selector.xpath('//p[@class="con"]') for useless in useless_list: useless.drop_tag() print(unescape(etree.tostring(selector).decode()))
運行效果以下圖所示。
成功達到了咱們想要的目的。
GNE 已經更新了版本,修復了這個 bug。使用 GNE 的同窗請升級到 0.1.5 以上版本:
pip install --upgrade gne
參考資料