python使用xslt提取網(wǎng)頁數(shù)據(jù)的方法
1、引言
在Python網(wǎng)絡爬蟲內(nèi)容提取器一文我們詳細講解了核心部件:可插拔的內(nèi)容提取器類gsExtractor。本文記錄了確定gsExtractor的技術路線過程中所做的編程實驗。這是第一部分,實驗了用xslt方式一次性提取靜態(tài)網(wǎng)頁內(nèi)容并轉換成xml格式。
2、用lxml庫實現(xiàn)網(wǎng)頁內(nèi)容提取
lxml是python的一個庫,可以迅速、靈活地處理 XML。它支持 XML Path Language (XPath) 和 Extensible Stylesheet Language Transformation (XSLT),并且實現(xiàn)了常見的 ElementTree API。
這2天測試了在python中通過xslt來提取網(wǎng)頁內(nèi)容,記錄如下:
2.1、抓取目標
假設要提取集搜客官網(wǎng)舊版論壇的帖子標題和回復數(shù),如下圖,要把整個列表提取出來,存成xml格式

2.2、源代碼1:只抓當前頁,結果顯示在控制臺
Python的優(yōu)勢是用很少量代碼就能解決一個問題,請注意下面的代碼看起來很長,其實python函數(shù)調(diào)用沒有幾個,大篇幅被一個xslt腳本占去了,在這段代碼中,只是一個好長的字符串而已,至于為什么選擇xslt,而不是離散的xpath或者讓人撓頭的正則表達式,請參看《Python即時網(wǎng)絡爬蟲項目啟動說明》,我們期望通過這個架構,把程序員的時間節(jié)省下來一大半。
可以拷貝運行下面的代碼(在windows10, python3.2下測試通過):
from urllib import request
from lxml import etree
url="http://www.gooseeker.com/cn/forum/7"
conn = request.urlopen(url)
doc = etree.HTML(conn.read())
xslt_root = etree.XML("""\
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<列表>
<xsl:apply-templates select="http://*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表"/>
</列表>
</xsl:template>
<xsl:template match="table/tbody/tr[position()>=1]" mode="list">
<item>
<標題>
<xsl:value-of select="*//*[@class='topic']/a/text()"/>
<xsl:value-of select="*[@class='topic']/a/text()"/>
<xsl:if test="@class='topic'">
<xsl:value-of select="a/text()"/>
</xsl:if>
</標題>
<回復數(shù)>
<xsl:value-of select="*//*[@class='replies']/text()"/>
<xsl:value-of select="*[@class='replies']/text()"/>
<xsl:if test="@class='replies'">
<xsl:value-of select="text()"/>
</xsl:if>
</回復數(shù)>
</item>
</xsl:template>
<xsl:template match="http://*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表">
<item>
<list>
<xsl:apply-templates select="table/tbody/tr[position()>=1]" mode="list"/>
</list>
</item>
</xsl:template>
</xsl:stylesheet>""")
transform = etree.XSLT(xslt_root)
result_tree = transform(doc)
print(result_tree)
源代碼請通過本文結尾的GitHub源下載。
2.3、抓取結果
得到的抓取結果如下圖:

2.4、源代碼2:翻頁抓取,結果存入文件
我們對2.2的代碼再做進一步修改,增加翻頁抓取和存結果文件功能,代碼如下:
from urllib import request
from lxml import etree
import time
xslt_root = etree.XML("""\
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<列表>
<xsl:apply-templates select="http://*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表"/>
</列表>
</xsl:template>
<xsl:template match="table/tbody/tr[position()>=1]" mode="list">
<item>
<標題>
<xsl:value-of select="*//*[@class='topic']/a/text()"/>
<xsl:value-of select="*[@class='topic']/a/text()"/>
<xsl:if test="@class='topic'">
<xsl:value-of select="a/text()"/>
</xsl:if>
</標題>
<回復數(shù)>
<xsl:value-of select="*//*[@class='replies']/text()"/>
<xsl:value-of select="*[@class='replies']/text()"/>
<xsl:if test="@class='replies'">
<xsl:value-of select="text()"/>
</xsl:if>
</回復數(shù)>
</item>
</xsl:template>
<xsl:template match="http://*[@id='forum' and count(./table/tbody/tr[position()>=1 and count(.//*[@class='topic']/a/text())>0])>0]" mode="列表">
<item>
<list>
<xsl:apply-templates select="table/tbody/tr[position()>=1]" mode="list"/>
</list>
</item>
</xsl:template>
</xsl:stylesheet>""")
baseurl = "http://www.gooseeker.com/cn/forum/7"
basefilebegin = "jsk_bbs_"
basefileend = ".xml"
count = 1
while (count < 12):
url = baseurl + "?page=" + str(count)
conn = request.urlopen(url)
doc = etree.HTML(conn.read())
transform = etree.XSLT(xslt_root)
result_tree = transform(doc)
print(str(result_tree))
file_obj = open(basefilebegin+str(count)+basefileend,'w',encoding='UTF-8')
file_obj.write(str(result_tree))
file_obj.close()
count += 1
time.sleep(2)
我們增加了寫文件的代碼,還增加了一個循環(huán),構造每個翻頁的網(wǎng)址,但是,如果翻頁過程中網(wǎng)址總是不變怎么辦?其實這就是動態(tài)網(wǎng)頁內(nèi)容,下面會討論這個問題。
3、總結
這是開源Python通用爬蟲項目的驗證過程,在一個爬蟲框架里面,其它部分都容易做成通用的,就是網(wǎng)頁內(nèi)容提取和轉換成結構化的操作難于通用,我們稱之為提取器。但是,借助GooSeeker可視化提取規(guī)則生成器MS謀數(shù)臺 ,提取器的生成過程將變得很便捷,而且可以標準化插入,從而實現(xiàn)通用爬蟲,在后續(xù)的文章中會專門講解MS謀數(shù)臺與Python配合的具體方法。
4、接下來閱讀
本文介紹的方法通常用來抓取靜態(tài)網(wǎng)頁內(nèi)容,也就是所謂的html文檔中的內(nèi)容,目前很多網(wǎng)站內(nèi)容是用javascript動態(tài)生成的,一開始html是沒有這些內(nèi)容的,通過后加載方式添加進來,那么就需要采用動態(tài)技術,請閱讀《Python爬蟲使用Selenium+PhantomJS抓取Ajax和動態(tài)HTML內(nèi)容》
5、集搜客GooSeeker開源代碼下載源
1.GooSeeker開源Python網(wǎng)絡爬蟲GitHub源
6、文檔修改歷史
2016-05-26:V2.0,增補文字說明;把跟帖的代碼補充了進來
2016-05-29:V2.1,增加最后一章源代碼下載源
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
pyspark自定義UDAF函數(shù)調(diào)用報錯問題解決
這篇文章主要為大家介紹了pyspark自定義UDAF函數(shù)調(diào)用報錯問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
從np.random.normal()到正態(tài)分布的擬合操作
這篇文章主要介紹了從np.random.normal()到正態(tài)分布的擬合操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
django vue3實現(xiàn)大文件分段續(xù)傳(斷點續(xù)傳)
本文介紹了使用Django和Vue3實現(xiàn)大文件分段上傳(斷點續(xù)傳)的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-01-01
python數(shù)據(jù)可視化使用pyfinance分析證券收益示例詳解
這篇文章主要為大家介紹了python數(shù)據(jù)可視化使用pyfinance分析證券收益的示例詳解及pyfinance中returns模塊的應用,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-11-11
Python如何利用struct進行二進制文件或數(shù)據(jù)流
這篇文章主要介紹了Python如何利用struct進行二進制文件或數(shù)據(jù)流問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
Python控制臺輸出時刷新當前行內(nèi)容而不是輸出新行的實現(xiàn)
今天小編就為大家分享一篇Python控制臺輸出時刷新當前行內(nèi)容而不是輸出新行的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Python中encode和encoding的區(qū)別小結
encode和encoding在Python中雖然都與字符編碼相關,但它們的角色和用途是不同的,本文主要介紹了Python中encode和encoding的區(qū)別小結,具有一定的參考價值,感興趣的可以了解一下2024-03-03

