天天看點

html.parser python_python網絡爬蟲之LXML與HTMLParser

Python lxml包用于解析html和XML檔案,個人覺得比beautifulsoup要更靈活些

Lxml中的路徑表達式如下:

html.parser python_python網絡爬蟲之LXML與HTMLParser

在下面的表格中,我們已列出了一些路徑表達式以及表達式的結果:

html.parser python_python網絡爬蟲之LXML與HTMLParser
html.parser python_python網絡爬蟲之LXML與HTMLParser

路徑表示中還可以選取多個路徑,使用’|’運算符,比如下面的樣子:

//book/title | //book/price 選取book 元素的所有title 和price 元素。

下面就來看下lxml的用法:還是用我們之前用過的網站,代碼如下:

fromlxml importetree

defparse_url_xml():

try:

req=urllib2.Request('http://www.xunsee.com/article/8c39f5a0-ca54-44d7-86cc-148eee4d6615/index.shtml')

fd=urllib2.urlopen(req)

html=etree.HTML(fd.read())

result=html.xpath('//*[@id="content_1"]/span[7]/a')

printtype(result)

forr inresult:

printr.text

exceptBaseException,e:

printe

首先使用etree,然後利用etree.HTML()初始化。然後用xpath進行查找。其中xpath中的//*[@id="content_1"]/span[7]/a就是網頁元素的xpath位址

html.parser python_python網絡爬蟲之LXML與HTMLParser

從表達式中可以看到首先找到id屬性為content_1的任意标簽。//*表示不管位置,隻管後面的屬性滿足即可。然後往下查找第7個span标簽,找到下面a的标簽。然後的result是一個清單。代表找到的所有的元素。通過周遊清單列印出内容。運作結果如下:

E:\python2.7.11\python.exe E:/py_prj/test.py

第7節

從上面可以看出,其實xpath還是很好寫,相對beautifulsoup對元素的定位更加準确。其實如果嫌麻煩,不想寫xpath,還有一個更簡單的方法。在浏覽器中按F12,在網頁源代碼中找到想定位的元素,然後滑鼠右鍵,點選Copy Xpath就可以得到xpath路徑

html.parser python_python網絡爬蟲之LXML與HTMLParser

下面再多舉幾個例子:比如擷取到最後一個span元素,可以用到下面的例子

result=html.xpath('//*[@id="content_1"]/span[last()]/a')

結果如下:

E:\python2.7.11\python.exe E:/py_prj/test.py

第657節

我們還可以精簡剛才用到的//*[@id="content_1"]/span[7]/a

精簡為://*[@href="7.shtml" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ]表示直接查找屬性為7.shtml的元素

如果想傳回多個元素,則可以用下面的方式,表示反悔第7節和第8節

result=html.xpath('//*[@href="7.shtml" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ] | //*[@href="8.shtml" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ]')

如果想得到所找節點的屬性值:可以用get的方法

result=html.xpath('//*[@href="7.shtml" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ] | //*[@href="8.shtml" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ]')

printtype(result)

forr inresult:

printr.get('href')

結果就會顯示節點href屬性的值

E:\python2.7.11\python.exe E:/py_prj/test.py

7.shtml

8.shtml

下面介紹下HTMLParser的用法:

HTMLParser是python自帶的網頁解析工具,使用很簡單。便于HTML檔案的解析

下面我們來看相關代碼:

classNewparser(HTMLParser):

def__init__(self):

HTMLParser.__init__(self)

self.flag=False

self.text=[]

defhandle_starttag(self,tag,attrs):

iftag == 'span':

self.flag=True

defhandle_data(self, data):

ifself.flag == True:

printdata

self.text.append(data)

defhandle_endtag(self, tag):

iftag == 'span':

self.flag=False

if__name__=="__main__":

parser=Newparser()

try:

req=urllib2.Request('http://www.xunsee.com/article/8c39f5a0-ca54-44d7-86cc-148eee4d6615/index.shtml')

fd=urllib2.urlopen(req)

parser.feed(fd.read())

printparser.text

exceptBaseException,e:

printe

首先定義一個類繼承自HTMLParser.在__init__函數中定義一些自己的參數。

parser.feed(fd.read()) 其中feed函數是類自帶的函數。參數就是網頁的HTML代碼。其中feed相當于一個驅動函數。我們來看下feed函數的原型。下面是feed的實作。可以看到實作了2個功能。其中就是将傳入的網頁代碼指派給rawdata。然後運作goahead開始進行處理

deffeed(self, data):

r"""Feed data to the parser.

Call this as often as you want, with as little or as much text

as you want (may include '\n').

"""self.rawdata = self.rawdata + data

self.goahead(0)

goahead函數代碼過多,這裡就不全部貼出來,具體功能就是周遊rawdata每行資料。然後根據的不同辨別調用不同的函數。關鍵函數如下。可以看到當遇到’

html.parser python_python網絡爬蟲之LXML與HTMLParser

parse_startag裡面實作handle_starttag,parse_endtag裡面實作handle_endtag。

代碼中的handle_starttag和handle_endtag是個空函數。隻是傳入了目前的tag以及attrs.這就給了我們重寫此函數的機會

defhandle_starttag(self, tag, attrs):

pass

defhandle_endtag(self, tag):

pass

defhandle_data(self, data):

pass

其中hanle_data是處理網頁代碼中的具體資料

說了這麼多,應該對HTMLParser的實作很清楚了。對每行網頁代碼進行處理。依次判斷是否進入handle_starttag,handle_endtag,handle_data。HTMLParser為我們解析出了每行的tag,attrs以及data。我們通過重寫這些函數提取我們需要的資訊。那麼回到我們的之前的代碼,這個代碼我們要實作的功能是将的字段提取出來。

首先__init__定義了2個參數,flag以及text,flag初始值為False

def__init__(self):

HTMLParser.__init__(self)

self.flag=False

self.text=[]

handle_starttag中實作隻要tag=span,那麼設定flag為True

defhandle_starttag(self,tag,attrs):

iftag == 'span':

self.flag=True

handle_data中實作隻要flag=True則提取出data資料并儲存在text清單裡面

defhandle_data(self, data):

ifself.flag == True:

printdata

self.text.append(data)

那麼這個提取資料的動作在什麼時候結束呢:這就要看handle_endtag了。同樣的在遇到tag=span的時候,則設定flag=False。這樣就不會提取data資料了,直到遇到下一個tag=span的時候。

defhandle_endtag(self, tag):

iftag == 'span':

self.flag=False

這就是HTMLParser的全部功能。是不是比之前的Beautifulsoup以及lxml都感覺要簡潔明了很多呢。對于不規範的網頁,HTMLParser就比Beautifulsoup和lxml好使。下面列出所有的函數功能:

handle_startendtag  處理開始标簽和結束标簽handle_starttag     處理開始标簽,比如handle_endtag       處理結束标簽,比如handle_charref      處理特殊字元串,就是以開頭的,一般是内碼表示的字元handle_entityref    處理一些特殊字元,以&開頭的,比如 handle_data         處理資料,就是data中間的那些資料handle_comment      處理注釋handle_decl         處理的東西

其他的實作都大同小異。從下一章開始将介紹scrapy的用法