当前位置:网站首页>数据解析(XPath、BeautifulSoup、正则表达式、pyquery)
数据解析(XPath、BeautifulSoup、正则表达式、pyquery)
2022-08-08 12:50:00 【木落风高天宇开gy】
本文部分数据来自菜鸟教程。
在爬虫学习中,获取网页数据后,需要对数据进行。
有4种解析方式分别是:XPath、BeautifulSoup、正则表达式、pyquery
1、XPath
XPath需要依赖lxml库: 安装方式 pip install lxml

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式:
| 表达式 | 描述 |
|---|---|
| nodename | 选取此节点的所有子节点。 |
| / | 从根节点选取(取子节点)。 |
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置(取子孙节点)。 |
| . | 选取当前节点。 |
| .. | 选取当前节点的父节点。 |
| @ | 选取属性。 |
在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| bookstore | 选取 bookstore 元素的所有子节点。 |
| /bookstore | 选取根元素 bookstore。 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
| bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
| //book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
| bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
| //@lang | 选取名为 lang 的所有属性。 |
谓语(Predicates)
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| /bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
| /bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
| /bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
| /bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
| //title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
| //title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
| /bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
| /bookstore/book[price>35.00]//title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
| 通配符 | 描述 |
|---|---|
| * | 匹配任何元素节点。 |
| @* | 匹配任何属性节点。 |
| node() | 匹配任何类型的节点。 |
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| /bookstore/* | 选取 bookstore 元素的所有子元素。 |
| //* | 选取文档中的所有元素。 |
| //title[@*] | 选取所有带有属性的 title 元素。 |
选取若干路径
通过在路径表达式中使用"|"运算符,您可以选取若干个路径。
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
|---|---|
| //book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
| //title | //price | 选取文档中的所有 title 和 price 元素。 |
| /bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
举个例子:爬取起点小说网月票榜上的书名

import requests
from lxml import etree
url='https://www.qidian.com/rank/yuepiao/'
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
resp=requests.get(url,headers=headers)#发送请求
e=etree.HTML(resp.text) #类型转换 将str类型转换成class 'lxml.etree._Element'
names=e.xpath('//div[@class="book-mid-info"]/h2/a/text()')
print(names) 
2、BeautifulSoup
安装方式 pip install bs4
解析器一般选用第二个

举个栗子:
from bs4 import BeautifulSoup
html='''
<html>
<head>
<title>百度一下</title>
</head>
<body>
<h1 class="info bg" float='left'>百度搜索</h1>
<a href="http://www.baidu.com"> 百度</a>
<h2><!--注释的内容--></h2>
</body>
</html>
'''
bs=BeautifulSoup(html,'lxml') #调用解析器,创建对象
print(bs.title)
print(bs.h1.attrs)
#获取单个属性
print(bs.h1.get('class'))
print(bs.h1['class'])
print(bs.a['href'])
#获取内容
print('--------',bs.h2.string) #获取到h2标签中的注释的文本内容
print(bs.h2.text) #因为h2标签中没有正而八经的文本内容from bs4 import BeautifulSoup
html='''
<title>百度一下</title>
<div class="info" float="left">百度搜索</div>
<div class="info" float="right" id="gb">
<span>好好学习,天天向上</span>
<a href="http://www.baidu.com">官网</a>
</div>
<span>人生苦短,再来一碗</span>
'''
bs=BeautifulSoup(html,'lxml')
print(bs.title,type(bs.title))
print(bs.find('div',class_='info'),type(bs.find('div',class_='info'))) #获取第一个满足条件的标签
print('--------------------------------------')
print(bs.find_all('div',class_='info')) #得到的是一个标签的列表
print('--------------------------------------')
for item in bs.find_all('div',class_='info'):
print(item,type(item))
print('--------------------------------------')
print(bs.find_all('div',attrs={'float':'right'}))
print('===============CSS选择器=======================')
print(bs.select("#gb"))
print('--------------------------------------')
print(bs.select('.info'))
print('--------------------------------------')
print(bs.select('div>span'))
print('--------------------------------------')
print(bs.select('div.info>span'))
for item in bs.select('div.info>span'):
print(item.text)
3、正则表达式
正则表达式 是一个特殊的字符序列,它能帮助用户便捷地检查一个字符串是否与某种模式匹配。 Python的正则模块是re,是Python的内置模块,不需要安装,导入即可。
语法:
序号 | 元字符 | 说明 |
1 | . | 匹配任意字符 |
2 | ^ | 匹配字符串的开头 |
3 | $ | 匹配字符的末尾 |
4 | * | 匹配前一个元字符0到多次 |
5 | + | 匹配前一个元字符1到多次 |
6 | ? | 匹配前一个元字符0到1次 |
7 | {m} | 匹配前一个字符m次 |
8 | {m,n} | 匹配前一个字符m到n次 |
9 | {m,n}? | 匹配前一个字符m到n次,并且取尽可能少的情况 |
10 | \\ | 对特殊字符进行转义 |
11 | [] | 一个字符的集合,可匹配其中任意一个字符 |
12 | | | 逻辑表达式”或”,比如a|b代表可匹配a或者b |
13 | (...) | 被括起来的表达式作为一个元组。findall()在有组的情况下只显示组的内容 |
特殊序列:
序号 | 元字符 | 说明 |
1 | \A | 只在字符串开头进行匹配 |
2 | \b | 匹配位于开头或者结尾的空字符串 |
3 | \B | 匹配不位于开头或者结尾的空字符串 |
4 | \d | 匹配任意十进制数,相当于[0-9] |
5 | \D | 匹配任意非数字字符,相当于[^0-9] |
6 | \s | 匹配任意空白字符,相当于[\t\n\r\f\v] |
7 | \S | 匹配任意非空白字符,相当于[^\t\n\r\f\v] |
8 | \w | 匹配任意数字、字母、下划线,相当于[a-zA-Z0-9_] |
9 | \W | 匹配任意非数字、字母、下划线,相当于[^a-zA-Z0-9_] |
10 | \Z | 只在字符串结尾进行匹配 |
11 | [\u4e00-\u9fa5] | 中文 |
正则处理函数:

自行用代码测试一下,加深理解, 代码里的 .group(),加上后方便看。去掉也可以
import re
s='Istudy study Python3.8 every day'
print('----------------match方法,从起始位置开始匹配------------')
print(re.match('I',s).group())
print(re.match('\w',s).group())
print(re.match('.',s).group())
print('---------------search方法,从任意位置开始匹配,匹配第一个---------------')
print(re.search('study',s).group())
print(re.search('s\w',s).group())
print('---------------findall方法,从任意位置开始匹配,匹配多个-----------------')
print(re.findall('y',s)) #结果为列表
print(re.findall('Python',s))
print(re.findall('P\w+.\d',s))
print(re.findall('P.+\d',s))
print('--------------sub方法的使用,替换功能-------------------------')
print(re.sub('study','like',s))
print(re.sub('s\w+','like',s))
4、pyquery
pyquery库是jQuery的Python实现,能够以jQuery的语法来操作解析 HTML 文档,易用性和解析速度都很好 前提条件: 你对CSS选择器与JQuery有所了解
非Python标准模块,需要安装 安装方式 pip install pyquery 测试方式 Import pyquery
序号 | 提取数据 | 举例 |
1 | 获取当前节点 | doc(‘#main’) |
2 | 获取子节点 | doc(‘#main’).children() |
3 | 获取父节点 | doc(‘#main’).parent() |
4 | 获取兄弟节点 | doc(‘#main’).siblings()方法 |
5 | 获取属性 | doc(‘#main’).attr(‘href’) |
6 | 获取内容 | doc(‘#main’).html() doc(‘#main’).text() |
from pyquery import PyQuery
html='''
<html>
<head>
<title>PyQuery</title>
</head>
<body>
<div id="main">
<a href="http://www.mashibing.com">马士兵教育</a>
<h1>欢迎来到马士兵教育</h1>
我是div中的文本
</div>
<h2>Python学习</h2>
</body>
</html>
'''
doc=PyQuery(html)
#获取当前节点
print(doc("#main"))
#获取父节点,子节点,兄弟节点
print('-----------父节点----------------')
print(doc("#main").parent())
print('-----------子节点----------------')
print(doc("#main").children())
print('-------------兄弟节点------------------')
print(doc("#main").siblings())
print('------------------获取属性---------------')
print(doc('a').attr('href'))
print('------------获取标签的内容----------------')
print(doc("#main").html())
print('-------------------------')
print(doc("#main").text())例子:爬取起点小说网月票榜的作者
import requests
from pyquery import PyQuery as pq
url='https://www.qidian.com/rank/yuepiao/'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}
resp=requests.get(url,headers=headers)
doc=pq(resp.text)#使用字符串初始化方式初始化PyQuery对象
authors=doc('p.author a')
authors_list=[]
for index in range(len(authors)):
if index%2==0:
authors_list.append(authors[index].text)
print(authors_list)
边栏推荐
- What is the IP SSL certificate, how to apply for?
- PE文件-手工修改重定位表-WinHex-CFF Explorer
- 海外邮件发送指南(一)
- R语言数据类型转换:基本数据类型的转换、将一种数据类型转化为另外一种数据类型
- The maximum validity period of an SSL certificate is 13 months. Is it necessary to apply for multiple years at a time?
- 各位,我想知道,既然数据全部读取过来存放内存,我flink sql窗口关闭之后再次查询这个cdc映射
- 如果Controller里有私有的方法,能成功访问吗?
- C language small project -- address book (static version + dynamic version + file version)
- 安装MinGW-w64
- 2020年是时候更新你的技术武器库了:Asgi vs Wsgi(FastAPI vs Flask)
猜你喜欢

如果Controller里有私有的方法,能成功访问吗?
深度剖析-class的几个对象(utlis,component)-瀑布流-懒加载(概念,作用,原理,实现步骤)

看到这个应用上下线方式,不禁感叹:优雅,太优雅了!

自动当道,效率至上 | 快来解锁财务共享服务中心数字化秘籍

The use of qsort function and its analog implementation

作为一个年薪50W阿里P7架构师的必备知识:并发+JVM+多线程+Netty+MySQL
![[C language] Detailed explanation of custom types: structure, enumeration, union](/img/5c/69d238a71e24b34c2232c20ed7e09e.png)
[C language] Detailed explanation of custom types: structure, enumeration, union

第十二届蓝桥杯《杨辉三角》-二分法

The most complete JVM performance tuning in history: thread + subsystem + class loading + memory allocation + garbage collection

phpstyle安装管理mysql
随机推荐
一文搞懂│XSS攻击、SQL注入、CSRF攻击、DDOS攻击、DNS劫持
使用.NET简单实现一个Redis的高性能克隆版(三)
移位运算、位运算、逻辑运算相关知识点及笔试题
Docker-持久化数据库(数据卷)
华中科大提出VGNetG:“不做选择,全都要”轻量化主干网络!
期货开户的交易通道和后续服务
Jenkins-安装(2)
STM32 entry development to make infrared remote control (smart home-universal remote control)
2022-08-04
行业领先的界面开发组件DevExpress 8月发布新版——v22.1.4
Prometheus监控Harbor(二进制版)
changes not staged for commit 解决办法
JPA之使用复合主键
医药行业转型发展,探索数字化供应链升级之道
(5)FlinkSQL将socket数据写入到mysql方式二
phpstyle安装管理mysql
SAP数据迁移需要多久?
The maximum validity period of an SSL certificate is 13 months. Is it necessary to apply for multiple years at a time?
三个点语法和DOM观察者
R语言ggplot2可视化:使用ggpubr包的ggdonutchart函数可视化甜甜圈图(donut chart)、为甜甜圈图添加自定义标签(包含文本内容以及数值百分比)、lab.font参数设置标