【Python爬虫】你还不知道选哪个解析网页的库吗,看我从此告别选择困难

🌈据说,看我文章时 关注、点赞、收藏帅哥美女们 心情都会不自觉的好起来。

前言:
🧡作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
✨个人主页:点我直达,在这里肯定能找到你想要的~
👍专栏介绍:Python爬虫 ,一个专注于分享爬虫技巧与案例的专栏~

专栏文章直链:
【Python爬虫】自从学会了autoscraper,每天再也不用手写解析爬虫了 (审核未通过,暂时无法重新发布)
【Python爬虫】你还在纠结选择哪个爬虫库嘛,全都拿来吧你
对旧博客反爬指导文章部分更新说明
beautifulsoup4无法正确解析网页的坑
QQ相关信息获取
Python爬取曾今的K歌
用“小聪明”实现连续爬取谷歌翻译
手把手带你用Python爬取反爬策略的网站

人生苦短,我用python

😁安装这些库

re库为标准库,不必安装,其他的在最后一行出现 Successfully installed XXX 就说明安装成功了!

pip install lxml
在这里插入图片描述
pip install pyquery
在这里插入图片描述
pip install bs4
在这里插入图片描述
pip install requests-html(他安装的库是真的多):
在这里插入图片描述

🤩解析数据部分

🚗万能的正则表达式

正则表达式相信大家都接触过,没有接触过的也可以查看我曾今发过的两篇博客:从常用实例学习正则1从常用实例学习正则2 来简单学习正则。
使用正则匹配网页中想要的数据时,有时候可能会设计比较复杂,比如:<img src="XXX" class="XX"> 如果你正则写的是 <img src="(.*?)" class="XX"> ,那么当网页源码变成<img class="XX" src="XXX"> 的时候,你就匹配不到结果了。所以正则匹配网页还是尽可能要广泛匹配,比如使用src="(.*?)" 不过这又可能匹配到其他地方。于是我们修改为 <img.*src="XXX"> ,这样能匹配所有img中的src属性,但这够了吗?这还不够,如果想要爬指定classimgsrc属性怎么办…
所以使用正则,虽然看着写的不算多,但考虑设计正则表达式还是要花一番功夫的,而且不方便看懂,不方便后期维护。
接下来来看个实例:
首先先把本文所需的所有库和网页源码准备好,本文其他代码中就不在区分引用了:

import re
import requests
from lxml import etree
from pyquery import PyQuery
from bs4 import BeautifulSoup
from requests_html import HTMLSession

url = 'http://110.42.181.215:8866'
html = requests.get(url).text

然后呢,给自己一个需求,比如我要提取网页中id="plans"的子元素中idplan2ondblclick属性:

result = re.findall(r'οndblclick=\"(.*?)\"', re.findall(r'<div.*?id=\"plan2\".*?>', html)[0])[0]
# result结果:set_direction('plan2')

其他的什么网址、标题等都需要结合实际场景编写正则表达式,一般第一次提取出所有有关的标签,第二次才提取属性值,如果需要同时锁定styleclass等,则需要多次匹配以确保在没有顺序的情况下能够准确获取。

🚕lxml.etree

虽然这个库并不是那么常用,但功能也挺强大的:

支持缺失自动补全

root = etree.HTML(html)

美化打印

print(etree.tostring(root, encoding=str, pretty_print=True))
# 返回:<html>......(此处省略 n 字)</html>

使用xpath获取标签,一般在浏览器开发工具里元素上右击都能找到复制XPath,这里就不教学了

plan = root.xpath('//*[@id="plans"]/div[2]')[0]

使用css选择器获取标签,一般在浏览器开发工具里元素上右击都能找到复制selector,这里就不教学了【不支持伪元素写法】

plan2 = root.cssselect('#plans>div')[1]

两种获取到的是同一个标签

print(plan == plan2)
# 返回:True

获取ondblclick属性

print(plan.get('ondblclick'))
# 返回:set_direction('plan2')

🚓pyquery.PyQuery

这个库是我用的最舒服的一个css选择器库了,没有之一,感觉上就像在用jquery。

加载源代码

q = PyQuery(html)

默认直接是支持伪元素的css选择器。有一种使用jquery选择元素的既视感,要不是python不能使用 $ 做变量名,不然写python代码就感觉在写jquery代码

tip = q('.tip')
plan = q('#plans>div:eq(1)')

直接打印返回HTML代码

print(plan)
# 返回:<div id="plan2" draggable="true" οndragstart="drag(event)" οndblclick="set_direction('plan2')"/>

相当于返回JavaScript中的 Element.innerText

print(tip.text())
# 返回:
# 游戏说明:
# 1、点击创建房间获取房间号,邀请另一半输入房间号即可加入房间。
# 2、如果电脑屏幕分辨率较低,可以按住 Ctrl 和鼠标滚轮调整缩放,推荐使用1920x1080分辨率。
# 3、如果击中敌方飞机则方块变红,否则方块变白;击中飞机核心(红色虚线)则整个飞机都会显示且变灰(代表已被击毁),比谁能更快击毁对方三架飞机吧~
# 4、每个人都要放置3架飞机,一旦放下不可更改,拖动到我方飞机区域(左)内即可,双击可以顺时针调整方向,拖动时请将飞机核心(红色虚线)对准拖动后的方块。
# 5、本游戏为回合制游戏,先摆放完者将先手,点击敌方飞机区域(右)进行攻击,击中飞机中心(红虚线边框方块)则飞机立刻坠毁,坠毁后会在图中显示飞机轮廓,不可撤销攻击,请谨慎攻击。

相当于返回JavaScript中的 Element.innerHTML

print(tip.html())
# 返回:
# 			<h3>游戏说明:</h3>
# 			<p>1、点击创建房间获取房间号,邀请另一半输入房间号即可加入房间。</p>
# 			<p>2、如果电脑屏幕分辨率较低,可以按住 Ctrl 和鼠标滚轮调整缩放,推荐使用<b><span style="color: red;">1920x1080</span></b>分辨率。</p>
# 			<p>3、如果击中敌方飞机则方块变红,否则方块变白;击中飞机核心(红色虚线)则整个飞机都会显示且变灰(代表已被击毁),比谁能更快击毁对方三架飞机吧~</p>
# 			<p>4、每个人都要放置3架飞机,一旦放下不可更改,拖动到我方飞机区域(左)内即可,双击可以顺时针调整方向,拖动时请将飞机核心(红色虚线)对准拖动后的方块。</p>
# 			<p>5、本游戏为回合制游戏,先摆放完者将先手,点击敌方飞机区域(右)进行攻击,击中飞机中心(红虚线边框方块)则飞机立刻坠毁,坠毁后会在图中显示飞机轮廓,不可撤销攻击,请谨慎攻击。</p>

可以在选择到的元素上继续选择

print(tip('p:eq(0)'))
# 返回:<p>1、点击创建房间获取房间号,邀请另一半输入房间号即可加入房间。</p>

可以直接查找到所有p标签

print(tip.find('p'))
# 返回:
# <p>1、点击创建房间获取房间号,邀请另一半输入房间号即可加入房间。</p>
# 			<p>2、如果电脑屏幕分辨率较低,可以按住 Ctrl 和鼠标滚轮调整缩放,推荐使用<b><span style="color: red;">1920x1080</span></b>分辨率。</p>
# 			<p>3、如果击中敌方飞机则方块变红,否则方块变白;击中飞机核心(红色虚线)则整个飞机都会显示且变灰(代表已被击毁),比谁能更快击毁对方三架飞机吧~</p>
# 			<p>4、每个人都要放置3架飞机,一旦放下不可更改,拖动到我方飞机区域(左)内即可,双击可以顺时针调整方向,拖动时请将飞机核心(红色虚线)对准拖动后的方块。</p>
# 			<p>5、本游戏为回合制游戏,先摆放完者将先手,点击敌方飞机区域(右)进行攻击,击中飞机中心(红虚线边框方块)则飞机立刻坠毁,坠毁后会在图中显示飞机轮廓,不可撤销攻击,请谨慎攻击。</p>

🛺bs4.BeautifulSoup

这应该是最大众的库了,相信不少人都用过。

加载解析网页。第二个位置参数是features是特征的意思,支持不同解析库:lxml、lxml-xml、html.parser、html5lib

soup = BeautifulSoup(html, 'lxml')

格式化网页字符串(缩进单位为1空格)

html = soup.prettify()
print(html)
# 返回:<html>......(此处省略 n 字)</html>

找到第一个符合的标签元素

sky = soup.find('div', attrs={'class': 'sky'}) 
print(sky)
# 返回:
# <div class="sky left">
# <center>我方飞机区域</center>
# <div id="left" οndragοver="allowDrop(event)" οndrοp="drop(event)"></div>
# </div>

找到所有符合的标签元素,可以使用class_来表示class类属性

sky = soup.find_all('div', class_='sky')
print(sky)
# 返回:
# [<div class="sky left">
# <center>我方飞机区域</center>
# <div id="left" οndragοver="allowDrop(event)" οndrοp="drop(event)"></div>
# </div>, <div class="sky right">
# <center>敌方飞机区域</center>
# <div id="right"></div>
# </div>]

可以从连续寻找标签元素

plans = soup.find('div', attrs={'id': 'plans'}).find_all('div')
print(plans)
# 返回:[<div draggable="true" id="plan1" οndblclick="set_direction('plan1')" οndragstart="drag(event)"></div>, <div draggable="true" id="plan2" οndblclick="set_direction('plan2')" οndragstart="drag(event)"></div>, <div draggable="true" id="plan3" οndblclick="set_direction('plan3')" οndragstart="drag(event)"></div>]

使用css选择器获取标签元素【不支持伪元素写法】

plan1 = soup.select('div#plan1')[0]
print(plan1)
# 返回:<div draggable="true" id="plan1" οndblclick="set_direction('plan1')" οndragstart="drag(event)"></div>

获取元素属性

print(plan1.get_attribute_list('ondblclick'))
# 返回:["set_direction('plan1')"]

获取元素所有属性字典

print(plan1.attrs)
# 返回:{'id': 'plan1', 'draggable': 'true', 'ondragstart': 'drag(event)', 'ondblclick': "set_direction('plan1')"}

获取提示标签中文字内容

print(soup.find('div', attrs={'class': 'tip'}).text)
# 返回:
# 游戏说明:
# 1、点击创建房间获取房间号,邀请另一半输入房间号即可加入房间。
# 2、如果电脑屏幕分辨率较低,可以按住 Ctrl 和鼠标滚轮调整缩放,推荐使用1920x1080分辨率。
# 3、如果击中敌方飞机则方块变红,否则方块变白;击中飞机核心(红色虚线)则整个飞机都会显示且变灰(代表已被击毁),比谁能更快击毁对方三架飞机吧~
# 4、每个人都要放置3架飞机,一旦放下不可更改,拖动到我方飞机区域(左)内即可,双击可以顺时针调整方向,拖动时请将飞机核心(红色虚线)对准拖动后的方块。
# 5、本游戏为回合制游戏,先摆放完者将先手,点击敌方飞机区域(右)进行攻击,击中飞机中心(红虚线边框方块)则飞机立刻坠毁,坠毁后会在图中显示飞机轮廓,不可撤销攻击,请谨慎攻击。

🚙requests_html.HTMLSession

这个库是爬取解析一体库,能自动将爬到的东西进行解析,其官网上介绍了他的优点:

  • 完整的 JavaScript 支持!
  • CSS 选择器(又名 jQuery 风格,感谢 PyQuery)。
  • XPath 选择器,适合胆小的人。
  • 模拟用户代理(就像一个真正的网络浏览器)。
  • 自动跟踪重定向。
  • 连接池和 cookie 持久性。
  • 您熟悉和喜爱的请求体验,具有神奇的解析能力。
  • 异步支持
    它只支持python3.6及以上,现在应该基本不会用低版本了吧,高版本多好玩~

访问网页

session = HTMLSession()
html = session.get(url)

返回的属性

print(html)
# 返回:<Response [200]>
print(html.html)
# 返回:<HTML url='http://110.42.181.215:8866/'>
print(html.html.html)
# 返回:<html>......(此处省略 n 字)</html>

查找元素

print(html.html.find('#plan2')[0].attrs)
# 返回:{'id': 'plan2', 'draggable': 'true', 'ondragstart': 'drag(event)', 'ondblclick': "set_direction('plan2')"}
print(html.html.find('#plans>div:eq(0)')[0])
# 返回:<Element 'div' id='plan1' draggable='true' οndragstart='drag(event)' οndblclick="set_direction('plan1')">
print(html.html.xpath('/html/body/center/div[2]/center')[0].text)
# 返回:我方飞机区域

搜索文字

print(html.html.search('推荐使用{}分辨率')[0])
# 返回:<b><span style="color: red;">1920x1080</span></b>
print(html.html.search('如果击中敌方飞机则方块{red},否则方块{white};击中飞机核心(红色虚线)则整个飞机都会显示且{gray}(代表已被击毁)')['gray'])
# 返回:变灰

JavaScript支持,经过此操作之后,网页将会加载JavaScript,并将加载后的网页传回使用。
他会自动下载chromium,缺点可能是下载太慢了,要个大约10分钟
requests-html在某些方面并不一定能代替requests+BeautifulSoup这对完美组合,但正是因为这些优秀的库才让我们现在编写爬虫越来越简单

html.html.render()

智能分页——默认通过查找a标签内是否有 [‘next’, ‘more’, ‘older’] ,看上去智能,但显得有点不灵活,如果可以的话还是希望能改改

for h in session.get('https://www.python.org/jobs/').html:
    print(h)
# 返回:
# <HTML url='https://www.python.org/jobs/'>
# <HTML url='https://www.python.org/jobs/?page=2'>
# <HTML url='https://www.python.org/jobs/?page=3'>
# <HTML url='https://www.python.org/jobs/?page=4'>
# <HTML url='https://www.python.org/jobs/?page=5'>
# <HTML url='https://www.python.org/jobs/?page=6'>
# <HTML url='https://www.python.org/jobs/?page=7'>
# <HTML url='https://www.python.org/jobs/?page=8'>
# <HTML url='https://www.python.org/jobs/?page=9'>

结束语

喜欢的三连关注我哦~

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值