1. 程式人生 > >python爬蟲(三)xpath與lxml

python爬蟲(三)xpath與lxml

XPath

XPath是一種在xml中查詢資訊的語言,可以用來在xml文件中對元素和屬性進行遍歷。
XPath使用路徑表示式在xml文件中選取節點,這裡注意需要逐級表現要選取節點的父子關係。

XPath符號

  • nodename 選取此節點的所有子節點
  • / 從根節點選取
  • // 從匹配選擇的當前節點文件中,而不考慮他們位置
  • . 選取當前節點。
  • .. 選取當前節點的父節點
  • @ 選取屬性
  • * 表示通配
  • | 連線多個表示式,做並集操作

XPath路徑表達

  • bookstore 選取bookstore元素的所有子節點。
  • /bookstore 選取根元素bookstore。
    • 假如路徑起始於正斜槓 。註釋:假如路徑起始於正斜槓 。註釋:假如路徑起始於正斜槓 。註釋:假如路徑起始於正斜槓 ( / ( / ),則此路徑始 ,則此路徑始 終代表到某元素的絕對路徑!
  • bookstore/book 選取bookstore子元素中所有book元素。
  • //book選取所有book元素,而不管它們在文件中的位置。
  • bookstore//book bookstore 選擇bookstore元素的後代中所有book元素,而不管它們位於bookstore下的什麼位置
  • //@auth 選取所有名為auth的屬性

XPath謂語

謂語表達了針對該層級節點的篩選條件,常見謂語如下

  • /book[2] 表示在該級選取第二個book節點
  • /book[last()] 表示在該級選取最後一個book節點
  • /book[position()<5] 表示在該級選取前四個book節點
  • /book[@auth]
    表示在該級選取所有擁有auth屬性的book節點
  • /book[@auth="buka"] 表示在該級選取所有auth屬性值為buka的book節點
  • /book[price>35.00] 表示在該級選取price子元素的值大於35的book節點

lxml庫

lxml是一個用於靈活處理xml格式資料的庫,此處可以用來幫助做網頁解析。
lxml用來做網頁解析的時候最常用的是其中的etree物件(lxml庫需保持在3.8版本以下)

簡單頁面解析

import requests
from lxml import etree

res = requests.get('https://www.baidu.com/'
).text # 使用etree.HTML()完成標籤優化,準備解析 html = etree.HTML(res) print(html.xpath('string(//*[@id="u1"]/a[@name="tj_trtieba"]/@href)'))

頁面內容抓取

import requests
from lxml import etree
from urllib.parse import urljoin

# 本例實際使用requests+lxml來抓取python百例資訊
url = 'http://www.runoob.com/python/python-100-examples.html'
res = requests.get(url).text
html = etree.HTML(res)
li_list = html.xpath('//*[@id="content"]/ul/li')
exam_list = []
for li in li_list:
    href = li.xpath('a/@href')
    exam_url = urljoin(url, href[0])
    # 此處使用requests預設解析會亂碼,需要抓取正文手動解碼
    exam_res = requests.get(exam_url).content.decode('utf-8')
    exam_html = etree.HTML(exam_res)
    title = exam_html.xpath('string(//*[@id="content"]/h1)')
    quest = exam_html.xpath('string(//*[@id="content"]/p[2])')
    analyse = exam_html.xpath('string(//*[@id="content"]/p[3])')
    code = exam_html.xpath('string(//div[@class="hl-main"]|//pre[@class="prettyprint prettyprinted"])')
    exam_dict = {
        'title': title,
        'quest': quest,
        'analyse': analyse,
        'code': code
    }
    print(exam_dict)
    exam_list.append(exam_dict)

import pandas

df = pandas.DataFrame(exam_list, columns=['title', 'quest', 'analyse', 'code'])
df.to_csv('exam.csv')