拒絕想固然,不看文檔致使GNE 的隱祕 bug

拒絕想固然,不看文檔致使GNE 的隱祕 bug

拒絕想固然,不看文檔致使GNE 的隱祕 bug

攝影:產品經理
在杭州居然還能吃到豌豆尖,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

拒絕想固然,不看文檔致使GNE 的隱祕 bug
<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 已經更新了版本,修復了這個 bug。使用 GNE 的同窗請升級到 0.1.5 以上版本:

pip install --upgrade gne

參考資料

[1]
GNE: https://github.com/kingname/GeneralNewsExtractor

拒絕想固然,不看文檔致使GNE 的隱祕 bug

相關文章
相關標籤/搜索