一、简介
-
xpath 浏览器插件,安装之后可以直接在浏览器输入
xpath
进行测试# 开关快捷键 windows: Ctrl-Shift-X Mac: Command-Shift-X
-
简单流程
# 1、安装 lxml 库 $ pip install lxml # 或使用国内源 $ pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple # 2、导入 lxml.etree from lxml import etree # 3、解析本地文件:etree.parse() html_tree = etree.parse('xxx.html') # 4、解析服务器响应数据:etree.HTML() html_tree = etree.HTML(response.read().decode('utf-8')) # 5、xpath路径 html_tree.xpath('xpath路径')
-
xpath
严格遵守HTML
规范,所有标签必须闭合(结束符)。
二、使用
-
xpath 语法入门,使用案例简单列举:
路径表达式案例 含义 //
查找所有子孙节点,不考虑层级关系 /
直接找子节点 //div[@id]
查询有 id
属性的div
标签//@class
获得所有带 class
属性标签的class
属性值//div[contains(@id, "he")]
查询 id
属性包含he
的div
标签//div[starts-with(@id, "he")]
查询 id
属性以he
开头的div
标签//div/h1/text()
获得 div
标签内h1
标签的内容//div[@id="head" and @class="one"]
查找 id
属性为head
同时class
属性为one
的div
标签//div[@id="head"] | //div[@id="one"]
查找 id
属性为head
或id
属性为one
的div
标签 -
本地测试文件
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>Document</title> </head> <body> <ul> <li>北京</li> <li>上海</li> <li>深圳</li> <li>武汉</li> </ul> <ul> <li>大连</li> <li>沈阳</li> <li>长沙</li> </ul> </body> </html>
-
本地案例
# 导入 lxml.etree from lxml import etree # 解析本地文件(远程网页内容按上面使用流程替换就行) tree = etree.parse('test.html') # 查找 ul 下面带 id 属性的 li 标签 li_list = tree.xpath('//ul/li[@id]/text()') # ['北京', '上海', '深圳', '武汉'] li_list = tree.xpath('//li[@id]/text()') # ['北京', '上海', '深圳', '武汉'] # 查找 ul 下面 id 属性为 l1 的 li 标签 li_list = tree.xpath('//li[@id="l1"]/text()') # ['北京'] # 获取 ul 下面 id 属性为 l1 的 li 标签的内容 li_list = tree.xpath('//li[@id="l1"]/text()') # ['北京'] # 查找 ul 下面 id 属性为 l1 的 li 标签的 class 属性值 li_list = tree.xpath('//li[@id="l1"]/@class') # ['c1'] # 查找 id 属性中包含 3 的标签 li_list = tree.xpath('//ul/li[contains(@id, "3")]/text()') # ['深圳'] # 查找 id 属性中以 l 开头的标签 li_list = tree.xpath('//ul/li[starts-with(@id, "l")]/text()') # ['北京', '上海', '深圳', '武汉'] # 查找 id 属性为 l1 和 class 属性为 c1 的标签 li_list = tree.xpath('//ul/li[@id="l1" and @class="c1"]/text()') # ['北京'] # 查找 id 属性为 l1 或 id 属性为 l2 的标签 li_list = tree.xpath('//ul/li[@id="l1" | @class="c1"]/text()') # 错误写法 li_list = tree.xpath('//ul/li[@id="l1"]/text() | //ul/li[@id="l2"]/text()') # ['北京', '上海'] # 输出 # print(li_list) # print(len(li_list))
-
远程案例
# 使用 urllib import urllib.request # 使用 lxml from lxml import etree # 定义 header headers = { # UA 最基本的防爬识别 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36' } # 1、定义一个 https 的 url url = 'https://www.baidu.com' # 2、定义一个 Request 对象,urlopen 方法并不能直接带 header。 # 细节:为什么这里需要写 url=url 而有的地方不需要?因为 Request 构造方法传参顺序问题 Request(url, data=None, headers={} ...) request = urllib.request.Request(url=url, headers=headers) # 3、模拟浏览器向服务器发送请求 response = urllib.request.urlopen(request) # 3、获取内容字符串 content = response.read().decode('utf-8') # 4 输出 # print(content) # 5、解析服务器响应数据 tree = etree.HTML(content) # 是否存在 id 属性为 su 的标签 print(tree.xpath('//@id="su"')) # True # 获得 `百度一下` 四个字 print(tree.xpath('//input[@id="su"]/@value')) # ['百度一下']