欢迎访问我的网站与公众号!点击与扫码即可进入,谢谢关注!

xpath解析: 最常用且便捷高效的一种解析方式

使用快捷方法:打开F12,右键点击html节点复制xpath

xpath解析原理:

1. 实例化一个etree对象,将要解析的页面元am加载到该对象中
2. 调用etree对象中的xpath方法,结合xpath表达式实现标签定位和内容捕获

流程

  1. 安装 pip install lxml
  2. 导入 from lxml import etree
  3. 实例化etree对象:
    • 将本地的html文档中的源码加载到etree对象中:
      tree = etree.parse(filePath)
    • 将网络中获取的源码加载到etree中
      tree = etree.HTML('page text')

xpath表达式

res = tree.xpath(xpath表达式)

  1. /:表示从根节点开始定位,代表一个层级
    例,定位title: /html/head/title

  2. //:表示多层级,可以从任意位置开始定位
    例,定位title: //title

  3. 属性定位: 根据一个标签的属性来定位,tag[@attrName="attrValue"]
    定位一个带class='song'的div
    //div[@class="song"]

  4. 索引定位: 多个标签,索引是从1开始的
    定位指定div下的第三个p: //div[@clsss="song"]/p[3]

  5. 取文本(返回的都是列表)

    • /text() # 取的是列表,直系文本
    • //text() # 标签中的非直系文本,所有的子标签文本
  6. 取属性(返回的都是列表)
    /@src /@attrName 定位到标签,属性名前加/@

实例1: (58二手房:获取的标签循环后,定位问题)

1
2
3
4
5
6
7
8
9
10
11
import requests
page_text = requests.get(url=url,headers=headers).text
tree = etree.HTML(page_text, 'lxml')
# 获取的是li的列表
li_list = tree.xpath('//ul@class="house-list-wrap"/li')
f = open('1.txt', 'w')
for li in li_list:
# 循环每个li ./表示相对于li的层级
# text()获取的是一个列表['你好']
title = li.xpath('./div[2]/h2/a/text()')[0]
f.write(title+'\n')

实例2: (图片解析下载: 中文乱码问题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
url = 'http://pic.netbian.com/4kmeinv'
response = requests.get(url=url, headers=headers)
# 尝试手动设定响应数据编码,没有效果是有通用解决
# response.encoding = 'utf-8'
page_text = response.text
# 准备解析: src alt
tree = etree.html(page_text, 'lxml')
li_list = tree.xpath('//url[@class="slist"]//li')

# 准备文件夹
dir_name = './pic'
if not os.path.exists(dir_name):
os.mkdir(dir_name)

for li in li_list:
img_src = li.xpath('./a/img/@src')[0]
img_src = 'http://pic.netbian.com'+img_src
# 中文出现乱码
img_name = li.xpath('./a/img/@alt')[0] + 'jpg'
# 通用处理乱码解决方案
img_name = img_name.encode('iso-8859-1').decode('gbk')
# print(img_name, img_src)
# 请求图片
img_data = requests.get(url=img_src, headers=headers).content
img_path = dir_name+'/'+img_name
with open(img_path, 'wb') as f:
f.write(img_data)
print(img_name,'下载成功')

实例3: (全国城市获取:热门城市+全部城市)

分开解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tree = etree.HTML(page_text)
# 热门城市
host_li_list = tree.xpath('//@div[@class="bottom"]/ul/li')
all_hot_city_names =[]
for li in host_li_list:
hot_city_name = li.xpath('./a/text()')[0]
all_hot_city_names.append(hot_city_name)

# 所有城市
city_names_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
all_city_names = []
for li in city_names_list:
city_name = li.xpath('./a/text()')[0]
all_city_names.append(city_name)

同时解析,两者xpath不同

1
2
3
4
5
6
7
8
9
#	//@div[@class="bottom"]/ul/li/a
# //div[@class="bottom"]/ul/div[2]/li/a
# 中间用 | 分开
a_list = tree.xpath('//@div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
all_city_names = []
for li in a_list:
city_name = li.xpath('./a/text()')
all_city_names.append(city_name)
print(all_city_names)