Lxml 解析網頁用法筆記
用python的urllib2庫實現的獲取到網頁資料之後,使用lxml對獲取的網頁進行資料抓取。
1.匯入包 from lxml import etree
2.page = etree.HTML(html) 或者 page = etree.HTML(html.decode('utf-8'))
3.對Element物件(page)使用xpath篩選,返回一個列表(裡面的元素也是Element)
舉例:
<html> <head> <meta name="content-type" content="text/html; charset=utf-8" /> <title>示例</title> </head> <body> <h1 class="cl1">測試內容一</h1> <p style="font-size: 200%">測試內容二</p> 測試內容三 <p>測試內容四</p> <a href="http://www.baidu.com/" target="_blank">百度</a> <a href="http://www.google.com" target="_blank">谷歌</a> <a href="http://www.ali.com" target="_blank">阿里</a> <a href="http://game.tencent.com" target="_blank"><img src='www.baidu.com'/>騰訊</a> <a href="http://game.sina.com" target="_blank"><img src='www.baidu.com'/>新浪</a> <a href="http://www.huawei.com" target="_blank"><img src='www.baidu.com'/>華為</a> <a href="http://www.xiaomi.com" target="_blank"><img src='www.baidu.com'/>小米</a> </body> </html>
解析html
from lxml import etree
page = etree.HTML(html.decode('utf-8'))
獲取標籤
# a標籤
tags = page.xpath(u'/html/body/a')
print(tags)
# html 下的 body 下的所有 a
# 結果[<Element a at 0x34b1f08>, ...]
/html 整個網頁的根目錄
/html/body/a 獲取整個網頁<body>標籤下所有<a>標籤
//a 獲取html下所有a標籤,在本例中功能同上(所有a標籤都放在body下,別的地方沒有)
/descendant::a 等價於 //a descendant::字首可紙袋任意多層中間節點,也可以省略成一個“ /”
/html/body/*/a 表示取出body下第二級的所有a標籤,不管它的上級是什麼標籤,‘*’可以代表所有的節點名
獲取head裡面的標籤要特別一點 比如//html/head/* 或者//html/head/title
獲取節點(標籤)屬性:
for taga in tags: print(taga.attrib) # 獲取屬性: {'target': '_blank', 'href': 'http://www.ali.com'} print(taga.get('href')) # 獲取某一屬性:http://www.ali.com print(taga.text) # 獲取文字: 阿里
利用屬性篩選標籤
# 直接定位到<h1 class="cl1">測試內容一</h1>
hs = page.xpath("//h1[@class='heading']")
for h in hs:
print(h.values())
print(h.text)
# 列印結果:
# ['heading']
# 測試內容一
屬性可以寫@name,@id,@value,@src,@href...
如果沒有屬性,也可以使用text()(表示標籤內包含的內容)和positon()(獲取節點的位置)
示例:
a[position()=2] 表示取得第二個a節點,可以被省略為a[2]
需要注意數字定位和過濾條件的順序
/body/a[5][@name='hello'] 表示取下第五個a標籤,並且name必須是hello,否則為空
/body/a[@name='hello'][5] 表示取body下第五個name為hello的a標籤
preceding-sibling::和 following-sibling::
preceding-sibling::字首表示同一層的上一個節點
following-sibling::字首表示同一層的下一個節點
示例
//body//following-sibling::a 同層下一個a標籤
//body/h1/preceding-sibling::* 所有h1上所有h1同級的子標籤
tail獲取特殊內容
<a href="http://game.tencent.com" target="_blank"><img src='www.baidu.com'/>騰訊</a>
‘騰訊’兩個字在<img/>和</a>標籤中間,正常使用text是獲取不到內容的,需要使用taga.tail.strip()來獲取內容
tail的意思是結束節點前面的內容,就是<img/>和</a>標籤中間的內容
如果script與style標籤之間的內容影響解析頁面,或者頁面很不規則,可以使用lxml.html.clean模組。模組 lxml.html.clean 提供 一個Cleaner 類來清理 HTML 頁。它支援刪除嵌入或指令碼內容、 特殊標記、 CSS 樣式註釋或者更多。
cleaner = Cleaner(style=True, scripts=True,page_structure=False, safe_attrs_only=False)
print cleaner.clean_html(html)
注意,page_structure,safe_attrs_only為False時保證頁面的完整性,否則,這個Cleaner會把你的html結構與標籤裡的屬性都給清理了。使用Cleaner類要十分小心,小心擦槍走火。
忽略大小寫可以:
page = etree.HTML(html)
keyword_tag = page.xpath("//meta[translate(@name,'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz')='keywords']")