用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" rel="external nofollow" target="_blank">百度</a>
<a href="http://www.google.com" target="_blank" rel="external nofollow" target="_blank">谷歌</a>
<a href="http://www.ali.com" target="_blank" rel="external nofollow" target="_blank">阿裡</a>
<a href="http://game.tencent.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank"><img src='www.baidu.com'/>騰訊</a>
<a href="http://game.sina.com" target="_blank" rel="external nofollow" target="_blank"><img src='www.baidu.com'/>新浪</a>
<a href="http://www.huawei.com" target="_blank" rel="external nofollow" target="_blank"><img src='www.baidu.com'/>華為</a>
<a href="http://www.xiaomi.com" target="_blank" rel="external nofollow" 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" rel="external nofollow" target="_blank" rel="external nofollow" 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']")