Date: 2019-07-03
Author: Sun
XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。
- Chrome插件 XPath Helper
- Firefox插件 XPath Checker
附加:XPath Helper安装过程
(1)找到chrome_xpath_tools目录
(2)方式一:先导入crx文件,看是否可行
? 安装方式一:直接拖拽chrome.crx插件到谷歌浏览器的扩展程序里。使用快捷钱ctrl+shift+x调出插件,如果没有成功,安装方式二进行安装
(3)方式二:把你的插件扩展名改成rar,然后解压到chrome目录。再重新添加chrome目录到你的谷歌浏览的扩展程序里面。使用快捷键查看是否安装成功
- lxml 是一个支持XPATH语法的HTML/XML的解析库,主要的功能是解析和提取 HTML/XML 数据,我们可以利用XPath语法,来快速的定位特定元素以及节点信息。
- lxml和正则一样,也是用 C 实现的,是一款高性能的 Python HTML/XML 解析器。
- 兼容python2.7和python3.x的所有版本
- lxml 官方文档
- 路径 = 相对路径 | 绝对路径
"/"处在XPath表达式开头则表示文档根元素,(表达式中间作为分隔符用以分割每一个步进表达式)如:
/html/body/div
是一种绝对路径表示法,它表明是从文档根开始查找节点。如果路径前没有"/"这种表示法称为相对路径,表明从当前节点开始查找。
如:
body/div
- 路径表达式 = 步进表达式 或者 相对路径 "/"步进表达式。
- 步进表达式 = 轴 节点测试 谓词等组成
- 其中轴表示步进表达式选择的节点和当前上下文节点间的树状关系(层次关系),节点测试指定步进表达式选择的节点名称扩展名,谓词即相当于过滤表达式以进一步过滤细化节点集。
- 谓词可以是0个或多个。多个谓词用逻辑操作符and, or连接。取逻辑非用not()函数。
说明
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的
所谓节点(node),就是XML文件的最小构成单位,一共分成7种
语法
表达式 | 描述 | 实例 | |
---|---|---|---|
nodename | 选取nodename节点的所有子节点 | xpath(‘//div’) | 选取了div节点的所有子节点 |
/ | 从根节点选取 | xpath(‘/div’) | 从根节点上选取div节点 |
// | 选取所有的当前节点,不考虑他们的位置 | xpath(‘//div’) | 选取所有的div节点 |
. | 选取当前节点 | xpath(‘./div’) | 选取当前节点下的div节点 |
.. | 选取当前节点的父节点 | xpath(‘..’) | 回到上一个节点 |
@ | 选取属性 | xpath(’//@calss’) | 选取所有的class属性 |
说明
谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点
语法
表达式 | 结果 |
---|---|
xpath(‘/body/div[1]’) | 选取body下的第一个div节点 |
xpath(‘/body/div[last()]’) | 选取body下最后一个div节点 |
xpath(‘/body/div[last()-1]’) | 选取body下倒数第二个div节点 |
xpath(‘/body/div[positon()<3]’) | 选取body下前两个div节点 |
xpath(‘/body/div[@class]’) | 选取body下带有class属性的div节点 |
xpath(‘/body/div[@class=”main”]’) | 选取body下class属性为main的div节点 |
xpath(‘/body/div[price>35.00]’) | 选取body下price元素值大于35的div节点 |
说明
Xpath通过通配符来选取未知的XML元素
语法
表达式 | 结果 |
---|---|
xpath(’/div/*’) | 选取div下的所有子节点 |
xpath(‘/div[@*]’) | 选取所有带属性的div节点 |
说明
轴可以定义相对于当前节点的节点集
语法
轴名称 | 表达式 | 描述 |
---|---|---|
ancestor | xpath(‘./ancestor::*’) | 选取当前节点的所有先辈节点(父、祖父) |
ancestor-or-self | xpath(‘./ancestor-or-self::*’) | 选取当前节点的所有先辈节点以及节点本身 |
attribute | xpath(‘./attribute::*’) | 选取当前节点的所有属性 |
child | xpath(‘./child::*’) | 返回当前节点的所有子节点 |
descendant | xpath(‘./descendant::*’) | 返回当前节点的所有后代节点(子节点、孙节点) |
following | xpath(‘./following::*’) | 选取文档中当前节点结束标签后的所有节点 |
following-sibing | xpath(‘./following-sibing::*’) | 选取当前节点之后的兄弟节点 |
parent | xpath(‘./parent::*’) | 选取当前节点的父节点 |
preceding | xpath(‘./preceding::*’) | 选取文档中当前节点开始标签前的所有节点 |
preceding-sibling | xpath(‘./preceding-sibling::*’) | 选取当前节点之前的兄弟节点 |
self | xpath(‘./self::*’) | 选取当前节点 |
说明
使用功能函数能够更好的进行模糊搜索
语法
函数 | 用法 | 解释 |
---|---|---|
starts-with | xpath(‘//div[starts-with(@id,”test”)]‘) | 选取id值以test开头的div节点 |
contains | xpath(‘//div[contains(@id,”test”)]‘) | 选取id值包含test的div节点 |
and | xpath(‘//div[contains(@id,”test”) and contains(@id,”in”)]‘) | 选取id值包含ma和in的div节点 |
text() | xpath(‘//div[contains(text(),”test”)]‘) | 选取节点文本包含test的div节点 |
安装lxml
pip install lxml==4.3.0
pip install lxml-4.3.0-cp36-cp36m-win_amd64.whl
导入lxml
from lxml import etree
实例化ElementTree
用来解析字符串格式的HTML文档对象
root = etree.HTML(html)
从本地读取HTML文件
root = etree.parse('test.html',etree.HTMLParser())
result = etree.tostring(html, pretty_print=True)
利用xpath语法解析
result = root.xpath('//li')
注意事项
先确保html经过了utf-8解码,即code = html.decode(‘utf-8‘, ‘ignore‘),否则会出现解析出错情况。因为中文被编码成utf-8之后变成 ‘/u2541‘ 之类的形式,lxml一遇到 “/”就会认为其标签结束
案例1:
爬取百度贴吧楼主页面中图片
#coding=utf-8
from lxml import etree
import requests
num = 0
header = {'User-Agent':'Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11'}
def load_data(key, page_start, page_end):
url = 'https://tieba.baidu.com/f?ie=utf-8&kw=%s&pn=%d'
for page in range(page_start,page_end+1):
full_url = url%(key,(page-1)*50)
headers = {'User_Agent':'User-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11'}
response = requests.get(full_url,headers = headers,verify = False)
data = response.text
xml = etree.HTML(data)
lzs = xml.xpath('//div[@class="threadlist_lz clearfix"]/div/a/@href')
#进入楼主的帖子
for lz in lzs:
load_lz_detail(lz)
def load_lz_detail(lz_url):
url = 'https://tieba.baidu.com'+lz_url
header = {'User-Agent':'Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11'}
#使用requests进行数据加载
response = requests.request('GET',url,headers = header,verify = False)
html = response.text
xml = etree.HTML(html)
image_url = xml.xpath('//img[@class="BDE_Image"]/@src')
#获取了楼主详情页面的图片
for url in image_url:
load_lz_detail_image(url)
def load_lz_detail_image(url):
global num
response = requests.get(url,headers =header,verify = False)
num+=1
with open('./images/'+str(num)+'.jpg','wb') as file:
file.write(response.content)
if __name__ == '__main__':
key = input('请输入贴吧名称:')
page_start = int(input("请输入起始页"))
page_end = int(input('请输入末尾页'))
load_data(key, page_start, page_end)
案例2:
采用xpath爬取格言网数据
练习:
58同城租房信息
原文:https://www.cnblogs.com/sunBinary/p/11129800.html