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