1. 程式人生 > >Lxml 解析網頁用法筆記

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']")