python使用xslt提取網(wǎng)頁數(shù)據(jù)的方法
1、引言
在Python網(wǎng)絡(luò)爬蟲內(nèi)容提取器一文我們?cè)敿?xì)講解了核心部件:可插拔的內(nèi)容提取器類gsExtractor。本文記錄了確定gsExtractor的技術(shù)路線過程中所做的編程實(shí)驗(yàn)。這是第一部分,實(shí)驗(yàn)了用xslt方式一次性提取靜態(tài)網(wǎng)頁內(nèi)容并轉(zhuǎn)換成xml格式。
2、用lxml庫實(shí)現(xiàn)網(wǎng)頁內(nèi)容提取
lxml是python的一個(gè)庫,可以迅速、靈活地處理 XML。它支持 XML Path Language (XPath) 和 Extensible Stylesheet Language Transformation (XSLT),并且實(shí)現(xiàn)了常見的 ElementTree API。
這2天測(cè)試了在python中通過xslt來提取網(wǎng)頁內(nèi)容,記錄如下:
2.1、抓取目標(biāo)
假設(shè)要提取集搜客官網(wǎng)舊版論壇的帖子標(biāo)題和回復(fù)數(shù),如下圖,要把整個(gè)列表提取出來,存成xml格式
2.2、源代碼1:只抓當(dāng)前頁,結(jié)果顯示在控制臺(tái)
Python的優(yōu)勢(shì)是用很少量代碼就能解決一個(gè)問題,請(qǐng)注意下面的代碼看起來很長(zhǎng),其實(shí)python函數(shù)調(diào)用沒有幾個(gè),大篇幅被一個(gè)xslt腳本占去了,在這段代碼中,只是一個(gè)好長(zhǎng)的字符串而已,至于為什么選擇xslt,而不是離散的xpath或者讓人撓頭的正則表達(dá)式,請(qǐng)參看《Python即時(shí)網(wǎng)絡(luò)爬蟲項(xiàng)目啟動(dòng)說明》,我們期望通過這個(gè)架構(gòu),把程序員的時(shí)間節(jié)省下來一大半。
可以拷貝運(yùn)行下面的代碼(在windows10, python3.2下測(cè)試通過):
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> <標(biāo)題> <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> </標(biāo)題> <回復(fù)數(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> </回復(fù)數(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)
源代碼請(qǐng)通過本文結(jié)尾的GitHub源下載。
2.3、抓取結(jié)果
得到的抓取結(jié)果如下圖:
2.4、源代碼2:翻頁抓取,結(jié)果存入文件
我們對(duì)2.2的代碼再做進(jìn)一步修改,增加翻頁抓取和存結(jié)果文件功能,代碼如下:
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> <標(biāo)題> <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> </標(biāo)題> <回復(fù)數(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> </回復(fù)數(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)
我們?cè)黾恿藢懳募拇a,還增加了一個(gè)循環(huán),構(gòu)造每個(gè)翻頁的網(wǎng)址,但是,如果翻頁過程中網(wǎng)址總是不變?cè)趺崔k?其實(shí)這就是動(dòng)態(tài)網(wǎng)頁內(nèi)容,下面會(huì)討論這個(gè)問題。
3、總結(jié)
這是開源Python通用爬蟲項(xiàng)目的驗(yàn)證過程,在一個(gè)爬蟲框架里面,其它部分都容易做成通用的,就是網(wǎng)頁內(nèi)容提取和轉(zhuǎn)換成結(jié)構(gòu)化的操作難于通用,我們稱之為提取器。但是,借助GooSeeker可視化提取規(guī)則生成器MS謀數(shù)臺(tái) ,提取器的生成過程將變得很便捷,而且可以標(biāo)準(zhǔn)化插入,從而實(shí)現(xiàn)通用爬蟲,在后續(xù)的文章中會(huì)專門講解MS謀數(shù)臺(tái)與Python配合的具體方法。
4、接下來閱讀
本文介紹的方法通常用來抓取靜態(tài)網(wǎng)頁內(nèi)容,也就是所謂的html文檔中的內(nèi)容,目前很多網(wǎng)站內(nèi)容是用javascript動(dòng)態(tài)生成的,一開始html是沒有這些內(nèi)容的,通過后加載方式添加進(jìn)來,那么就需要采用動(dòng)態(tài)技術(shù),請(qǐng)閱讀《Python爬蟲使用Selenium+PhantomJS抓取Ajax和動(dòng)態(tài)HTML內(nèi)容》
5、集搜客GooSeeker開源代碼下載源
1.GooSeeker開源Python網(wǎng)絡(luò)爬蟲GitHub源
6、文檔修改歷史
2016-05-26:V2.0,增補(bǔ)文字說明;把跟帖的代碼補(bǔ)充了進(jìn)來
2016-05-29:V2.1,增加最后一章源代碼下載源
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python日期和時(shí)間戳的轉(zhuǎn)換的實(shí)現(xiàn)方式
Python中日期和時(shí)間的處理涉及到time和datetime模塊,time模塊可實(shí)現(xiàn)時(shí)間戳與格式化時(shí)間字符串的轉(zhuǎn)換,而datetime模塊則提供更加直接易用的接口,本文詳細(xì)給大家介紹了Python日期和時(shí)間戳的轉(zhuǎn)換的實(shí)現(xiàn)方式,需要的朋友可以參考下2024-10-10Python數(shù)據(jù)分析與處理(二)——處理中國(guó)地區(qū)信息
這篇文章主要介紹了Python數(shù)據(jù)分析與處理-處理中國(guó)地區(qū)信息,上文介紹了北京高考分?jǐn)?shù)線統(tǒng)計(jì)分析,這篇文章依然圍繞Python數(shù)據(jù)分析與處理的相關(guān)資料來介紹處理中國(guó)地區(qū)信息,需要的朋友可以參考一下2021-12-12python+selenium實(shí)現(xiàn)163郵箱自動(dòng)登陸的方法
本篇文章主要介紹了python+selenium實(shí)現(xiàn)163郵箱自動(dòng)登陸的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12python中threading和queue庫實(shí)現(xiàn)多線程編程
這篇文章主要介紹了python中threading和queue庫實(shí)現(xiàn)多線程編程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02Python?Celery定時(shí)任務(wù)詳細(xì)講解
這篇文章主要介紹了Python?Celery定時(shí)任務(wù)詳細(xì)講解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08python驗(yàn)證碼識(shí)別教程之利用滴水算法分割圖片
這篇文章主要給大家介紹了關(guān)于python驗(yàn)證碼識(shí)別教程之利用滴水算法分割圖片的相關(guān)資料,文章中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-06-06