Python lxml包用于解析html和XML檔案,個人覺得比beautifulsoup要更靈活些
Lxml中的路徑表達式如下:
在下面的表格中,我們已列出了一些路徑表達式以及表達式的結果:
路徑表示中還可以選取多個路徑,使用’|’運算符,比如下面的樣子:
//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位址
從表達式中可以看到首先找到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路徑
下面再多舉幾個例子:比如擷取到最後一個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每行資料。然後根據的不同辨別調用不同的函數。關鍵函數如下。可以看到當遇到’
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的用法