python爬虫 requests-html的使用


Posted in Python onNovember 30, 2020

一 介绍

Python上有一个非常著名的HTTP库——requests,相信大家都听说过,用过的人都说非常爽!现在requests库的作者又发布了一个新库,叫做requests-html,看名字也能猜出来,这是一个解析HTML的库,具备requests的功能以外,还新增了一些更加强大的功能,用起来比requests更爽!接下来我们来介绍一下它吧。

# 官网解释
'''
This library intends to make parsing HTML (e.g. scraping the web) as simple and intuitive as possible.
If you're interested in financially supporting Kenneth Reitz open source, consider visiting this link. Your support helps tremendously with sustainability of motivation, as Open Source is no longer part of my day job.
When using this library you automatically get:

Full JavaScript support!
CSS Selectors (a.k.a jQuery-style, thanks to PyQuery).
XPath Selectors, for the faint at heart.
Mocked user-agent (like a real web browser).
Automatic following of redirects.
Connection?pooling and cookie persistence.
The Requests experience you know and love, with magical parsing abilities.
Async Support
'''

官网告诉我们,它比原来的requests模块更加强大,并且为我们提供了一些新的功能!

  • 支持JavaScript
  • 支持CSS选择器(又名jQuery风格, 感谢PyQuery)
  • 支持Xpath选择器
  • 可自定义模拟User-Agent(模拟得更像真正的web浏览器)
  • 自动追踪重定向
  • 连接池与cookie持久化
  • 支持异步请求

二 安装

安装requests-html非常简单,一行命令即可做到。需要注意一点就是,requests-html只支持Python 3.6或以上的版本,所以使用老版本的Python的同学需要更新一下Python版本了。

# pip3 install requests-html

三 如何使用requests-html?

在我们学爬虫程序的时候用得最多的请求库就是requests与urllib,但问题是这些包只给我们提供了如何去目标站点发送请求,然后获取响应数据,接着再利用bs4或xpath解析库才能提取我们需要的数据。

以往爬虫的请求与解析

import requests
from bs4 import BeautifulSoup
url = 'http://www.zuihaodaxue.cn/'
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36'
}
response = requests.get(url, headers=HEADERS)
response.encoding = 'gbk'
# print(response.status_code)
 print(response.text)

soup = BeautifulSoup(response.text, 'lxml')
# 获取最新的五则新闻
post_rankings = soup.find_all(name='article', attrs={"class": "post_ranking"})
# 循环打印新闻简介内容
for post_ranking in post_rankings:
new = post_ranking.find(name='div', attrs={"class": 'post_summary'})
print(new.text)

而在requests-html里面只需要一步就可以完成而且可以直接进行js渲染!requests的作者Kenneth Reitz 开发的requests-html 爬虫包 是基于现有的框架 PyQuery、Requests、lxml、beautifulsoup4等库进行了二次封装,作者将Requests的简单,便捷,强大又做了一次升级。

requests-html和其他解析HTML库最大的不同点在于HTML解析库一般都是专用的,所以我们需要用另一个HTTP库先把网页下载下来,然后传给那些HTML解析库。而requests-html自带了这个功能,所以在爬取网页等方面非常方便。

1、基本使用

from requests_html import HTMLSession
# 获取请求对象
session = HTMLSession()
# 往新浪新闻主页发送get请求
sina = session.get('https://news.sina.com.cn/')
# print(sina.status_code)
sina.encoding = 'utf-8'
# 获取响应文本信息,与requests无区别
 print(sina.text)

2、获取链接(links与abolute_links)

links返回的结果

python爬虫 requests-html的使用 

absolute_links返回的结果

python爬虫 requests-html的使用

from requests_html import HTMLSession
# 获取请求对象
session = HTMLSession()
# 往京东主页发送get请求
jd = session.get('https://jd.com/')
# 得到京东主页所有的链接,返回的是一个set集合
print(jd.html.links)
print('*' * 1000)
# 若获取的链接中有相对路径,我们还可以通过absolute_links获取所有绝对链接
print(jd.html.absolute_links)

3、CSS选择器与XPATH

request-html支持CSS选择器和XPATH两种语法来选取HTML元素。首先先来看看CSS选择器语法,它需要使用HTML的find函数来查找元素。

'''
CSS选择器 and XPATH
 
1.通过css选择器选取一个Element对象
 
2.获取一个Element对象内的文本内容
 
3.获取一个Element对象的所有attributes
 
 4.渲染出一个Element对象的HTML内容
 
5.获取Element对象内的特定子Element对象,返回列表
 
6.在获取的页面中通过search查找文本
 
 7.支持XPath
 
 8.获取到只包含某些文本的Element对象
'''
from requests_html import HTMLSession
session = HTMLSession()
url = "https://www.qiushibaike.com/text/"
# 获取响应数据对象
obj = session.get(url)
# 1.通过css选择器选取一个Element对象
 获取id为content-left的div标签,并且返回一个对象
content = obj.html.find('div#content-left', first=True)
# 2.获取一个Element对象内的文本内容
 获取content内所有文本
print(content.text)
# 3.获取一个Element对象的所有attributes
 获取content内所有属性
print(content.attrs)
# 4.渲染出一个Element对象的完整的HTML内容
html = content.html
print(html)
# 5.获取Element对象内的指定的所有子Element对象,返回列表
a_s = content.find('a')
print(a_s)
print(len(a_s)) # 79
# 循环所有的a标签
for a in a_s:
# 获取a标签内所有属性的href属性 并拼接
href = a.attrs['href']
if href.startswith('/'):
url = 'https://www.qiushibaike.com' + href
print(url)
# 6.在获取的页面中通过search查找文本
 {}大括号相当于正则的从头到后开始匹配,获取当中想要获取的数据
text = obj.html.search('把{}夹')[0] # 获取从 "把" 到 "夹" 字的所有内容
text = obj.html.search('把糗事{}夹')[0] # 获取从把子到夹字的所有内容
print(text)
print('*' * 1000)
# 7.支持XPath
a_s = obj.html.xpath('//a') # 获取html内所有的a标签
for a in a_s:
href = a.attrs['href']
#若是//开头的url都扔掉
if href.startswith('continue#若是/开头的都是相对路径)
 elif href.startswith('/')
 print('https://www.qiushibaike.com'+href)

# 8.获取到只包含某些文本的Element对象(containing)
 获取所有文本内容为幽默笑话大全_爆笑笑话_笑破你的肚子的搞笑段子 - 糗事百科 title标签
 注意: 文本内有空格也必须把空格带上
title = obj.html.find('title', containing='幽默笑话大全_爆笑笑话_笑破你的肚子的搞笑段子 - 糗事百科')
print(title)

四支持JavaScript

支持JavaScript是我觉得作者更新后最为牛逼的一个地方,但是需要在第一次执行render的时候下载chromeium,然后通过它来执行js代码。

1、render的使用

from requests_html import HTMLSession
session = HTMLSession()
url = 'http://www.win4000.com/'
obj = session.get(url)
obj.encoding = 'utf-8'
obj.html.render()

注意:第一次运行render()方法时,它会将Chromium下载到您的主目录中(例如~/.pyppeteer/)。这种情况只发生一次。

2、 下载Chromeium问题

因为是从国外的站点下载几分钟才3%,实在是太慢了。所以我们需要通过国内的镜像去下载!需要做以下几步:

手动下载Chrome

先去国内源下载自己需要的版本,地址:https://npm.taobao.org/mirrors/chromium-browser-snapshots/

python爬虫 requests-html的使用

修改chromeium_downloader.py文件

下载后之后解压后,进入python安装目录下的\Lib\site-packages\pyppeteer目录, 并打开chromium_downloader.py文件。

# 找到自己的操作系统相应的配置位置
'''
chromiumExecutable = {
'linux': DOWNLOADS_FOLDER / REVISION / 'chrome-linux' / 'chrome',
'mac': (DOWNLOADS_FOLDER / REVISION / 'chrome-mac' / 'Chromium.app' /
'Contents' / 'MacOS' / 'Chromium'),
'win32': DOWNLOADS_FOLDER / REVISION / 'chrome-win32' / 'chrome.exe',
'win64': DOWNLOADS_FOLDER / REVISION / 'chrome-win32' / 'chrome.exe',
}
'''
from pyppeteer import __chromium_revision__, __pyppeteer_home__
DOWNLOADS_FOLDER = Path(pyppeteer_home) / 'local-chromium'
REVISION = os.environ.get('PYPPETEER_CHROMIUM_REVISION', chromium_revision)
# 打印这两个变量可以知道执行的驱动具体位置
print(DOWNLOADS_FOLDER)
print(REVISION)
'''
由上面可以知道:chromium路径是:C:\Users\Ray\AppData\Local\pyppeteer\pyppeteer\local-chromium\575458\chrome-win32\chrome.exe
所以自己建文件夹,然后一直到chrome-win32文件夹,把上面下载的chromium文件,拷贝到此目录下
'''

五 自定义User-Agent

有些网站会使用User-Agent来识别客户端类型,有时候需要伪造UA来实现某些操作。如果查看文档的话会发现HTMLSession上的很多请求方法都有一个额外的参数**kwargs,这个参数用来向底层的请求传递额外参数。我们先向网站发送一个请求,看看返回的网站信息。

from requests_html import HTMLSession
# pprint可以把数据打印得更整齐
from pprint import pprint
import json
get_url = 'http://httpbin.org/get'
session = HTMLSession()
# 返回的是当前系统的headers信息
res = session.get(get_url)
pprint(json.loads(res.html.html))
# 可以在发送请求的时候更换user-agent
ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0'
post_url = 'http://httpbin.org/get'
res = session.get(post_url, headers={'user-agent': ua})
pprint(json.loads(res.html.html))# 如果你有需要可以在header中修改其他参数。

六 模拟表单提交(POST)

HTMLSession封装了一整套的HTTP方法,包括get、post、delete等, 对应HTTP中各个方法。

# 表单登录
r = session.post('http://httpbin.org/post', data={'username': 'tank_jam', 'password': 'tank9527'})
pprint(json.loads(r.html.html))
''' # 打印结果
{'args': {},
 'data': '',
 'files': {},
 'form': {'password': 'tank9527', 'username': 'tank_jam'},
 'headers': {'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Length': '35',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Host': 'httpbin.org',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) '
       'AppleWebKit/603.3.8 (KHTML, like Gecko) '
       'Version/10.1.2 Safari/603.3.8'},
 'json': None,
 'origin': '112.65.61.109, 112.65.61.109',
 'url': 'https://httpbin.org/post'}
'''

七 支持异步请求

requests-html内部就封装好了aynsc异步请求的功能,可以提高我们的爬虫效率。

from requests_html import AsyncHTMLSession
from requests_html import HTMLSession
import time
# 使用异步发送请求
async_session = AsyncHTMLSession()
async def get_baidu():
url = 'https://www.baidu.com/'
res = await async_session.get(url)
print(res.html.absolute_links)
async def get_sougou():
url = 'https://www.sogou.com/'
res = await async_session.get(url)
print(res.html.links)
start_time = time.time()
async_session.run(get_baidu, get_sougou)
print('耗时:', time.time() - start_time)
# 同步发送请求
session = HTMLSession()
start_time = time.time()
res = session.get('https://www.baidu.com/')
print(res.html.links)
res = session.get('https://www.sogou.com/')
print(res.html.absolute_links)
print('耗时:', time.time() - start_time)

1. 开始

Python 中可以进行网页解析的库有很多,常见的有 BeautifulSoup 和 lxml 等。在网上玩爬虫的文章通常都是介绍 BeautifulSoup 这个库,我平常也是常用这个库,最近用 Xpath 用得比较多,使用 BeautifulSoup 就不大习惯,很久之前就知道 Reitz 大神出了一个叫 Requests-HTML 的库,一直没有兴趣看,这回可算歹着机会用一下了。

使用 pip install requests-html安装,上手和 Reitz 的其他库一样,轻松简单:

from requests_html import HTMLSession
 session = HTMLSession()
 ​
 r = session.get('https://www.python.org/jobs/')

这个库是在 requests 库上实现的,r 得到的结果是 Response 对象下面的一个子类,多个一个 html 的属性。所以 requests 库的响应对象可以进行什么操作,这个 r 也都可以。如果需要解析网页,直接获取响应对象的 html 属性:

r.html

2. 原理

不得不膜拜 Reitz 大神太会组装技术了。实际上 HTMLSession 是继承自 requests.Session 这个核心类,然后将 requests.Session 类里的 requests 方法改写,返回自己的一个 HTMLResponse 对象,这个类又是继承自 requests.Response,只是多加了一个 _from_response 的方法来构造实例:

class HTMLSession(requests.Session):
  # 重写 request 方法,返回 HTMLResponse 构造
  def request(self, *args, **kwargs) -> HTMLResponse:
   r = super(HTMLSession, self).request(*args, **kwargs)
   return HTMLResponse._from_response(r, self)
class HTMLResponse(requests.Response):
 # 构造器
  @classmethod
  def _from_response(cls, response, session: Union['HTMLSession', 'AsyncHTMLSession']):
   html_r = cls(session=session)
   html_r.__dict__.update(response.__dict__)
   return html_r

之后在 HTMLResponse 里定义属性方法 html,就可以通过 html 属性访问了,实现也就是组装 PyQuery 来干。核心的解析类也大多是使用 PyQuery 和 lxml 来做解析,简化了名称,挺讨巧的。

3. 元素定位

元素定位可以选择两种方式:

css 选择器

  • css选择器
  • xpath
# css 获取有多少个职位
 jobs = r.html.find("h1.call-to-action")
 # xpath 获取
 jobs = r.html.xpath("//h1[@class='call-to-action']")

方法名非常简单,符合 Python 优雅的风格,这里不妨对这两种方式简单的说明:

4. CSS 简单规则

  • 标签名 h1
  • id 使用 #id 表示
  • class 使用 .class_name 表示
  • 谓语表示:h1[prop=value]

5. Xpath简单规则

  • 路径 // 或者 /
  • 标签名
  • 谓语 [@prop=value]
  • 轴定位 名称::元素名[谓语]

定位到元素以后势必要获取元素里面的内容和属性相关数据,获取文本:

jobs.text
 jobs.full_text

获取元素的属性:

attrs = jobs.attrs
 value = attrs.get("key")

还可以通过模式来匹配对应的内容:

## 找某些内容匹配
 r.html.search("Python {}")
 r.html.search_all()

这个功能看起来比较鸡肋,可以深入研究优化一下,说不定能在 github 上混个提交。

6. 人性化操作

除了一些基础操作,这个库还提供了一些人性化的操作。比如一键获取网页的所有超链接,这对于整站爬虫应该是个福音,URL 管理比较方便:

r.html.absolute_links
 r.html.links

内容页面通常都是分页的,一次抓取不了太多,这个库可以获取分页信息:

print(r.html)
 # 比较一下
 for url in r.html:
  print(url)
 ​

结果如下:

# print(r.html)
 <HTML url='https://www.python.org/jobs/'>
 # for
 <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'>

通过迭代器实现了智能发现分页,这个迭代器里面会用一个叫 _next 的方法,贴一段源码感受下:

def get_next():
 candidates = self.find('a', containing=next_symbol)
 ​
 for candidate in candidates:
 if candidate.attrs.get('href'):
 # Support 'next' rel (e.g. reddit).
 if 'next' in candidate.attrs.get('rel', []):
 return candidate.attrs['href']

通过查找 a 标签里面是否含有指定的文本来判断是不是有下一页,通常我们的下一页都会通过 下一页 或者 加载更多 来引导,他就是利用这个标志来进行判断。默认的以列表形式存在全局:['next', 'more', 'older']。我个人认为这种方式非常不灵活,几乎没有扩展性。感兴趣的可以往 github 上提交代码优化。

7. 加载 js

也许是考虑到了现在 js 的一些异步加载,这个库支持 js 运行时,官方说明如下:

Reloads the response in Chromium, and replaces HTML contentwith an updated version, with JavaScript executed.

使用非常简单,直接调用以下方法:

r.html.render()

第一次使用的时候会下载 Chromium,不过国内你懂的,自己想办法去下吧,就不要等它自己下载了。render 函数可以使用 js 脚本来操作页面,滚动操作单独做了参数。这对于上拉加载等新式页面是非常友好的。

8. 总结

Reitz 大神设计出来的东西还是一如既往的简单好用,自己不多做,大多用别人的东西组装,简化 api。真是够人性。不过有的地方还是优化空间,希望有兴趣和精力的童鞋去 github 上关注一下这个项目。

到此这篇关于python爬虫 requests-html的使用的文章就介绍到这了,更多相关python requests-html内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python函数的周期性执行实现方法
Aug 13 Python
python实现unicode转中文及转换默认编码的方法
Apr 29 Python
python中退出多层循环的方法
Nov 27 Python
解决nohup执行python程序log文件写入不及时的问题
Jan 14 Python
django 通过url实现简单的权限控制的例子
Aug 16 Python
Python箱型图绘制与特征值获取过程解析
Oct 22 Python
python实现差分隐私Laplace机制详解
Nov 25 Python
Python实现随机取一个矩阵数组的某几行
Nov 26 Python
如何利用pycharm进行代码更新比较
Nov 04 Python
python中的unittest框架实例详解
Feb 05 Python
python 利用 PIL 将数组值转成图片的实现
Apr 12 Python
Python中rapidjson参数校验实现
Jul 25 Python
python实现登录与注册系统
Nov 30 #Python
python代码实现图书管理系统
Nov 30 #Python
python 爬虫网页登陆的简单实现
Nov 30 #Python
Prometheus开发中间件Exporter过程详解
Nov 30 #Python
python实现猜拳游戏项目
Nov 30 #Python
Python解析微信dat文件的方法
Nov 30 #Python
Python应用自动化部署工具Fabric原理及使用解析
Nov 30 #Python
You might like
如何写php程序?
2006/12/08 PHP
使用XHGui来测试PHP性能的教程
2015/07/03 PHP
PHP实现的线索二叉树及二叉树遍历方法详解
2016/04/25 PHP
PHP7+Nginx的配置与安装教程详解
2016/05/10 PHP
基于PHP实现短信验证码接口(容联运通讯)
2016/09/06 PHP
Yii2针对游客、用户防范规则和限制的解决方法分析
2016/10/08 PHP
jquery tools 系列 scrollable学习
2009/09/06 Javascript
DIY jquery plugin - tabs标签切换实现代码
2010/12/11 Javascript
getComputedStyle与currentStyle获取样式(style/class)
2013/03/19 Javascript
JavaScript字符串常用类使用方法汇总
2015/04/14 Javascript
jquery简单实现幻灯片的方法
2015/08/03 Javascript
javascript正则表达式定义(语法)总结
2016/01/08 Javascript
jquery mobile实现可折叠的导航按钮
2017/03/11 Javascript
webpack4 处理CSS的方法示例
2018/09/03 Javascript
element el-input directive数字进行控制
2018/10/11 Javascript
js实现全选反选不选功能代码详解
2019/04/24 Javascript
Echarts动态加载多条折线图的实现代码
2019/05/24 Javascript
vue如何搭建多页面多系统应用
2020/06/17 Javascript
Python functools模块学习总结
2015/05/09 Python
python socket网络编程之粘包问题详解
2018/04/28 Python
使用Python正则表达式操作文本数据的方法
2019/05/14 Python
python连接mysql有哪些方法
2020/06/24 Python
解析python 类方法、对象方法、静态方法
2020/08/15 Python
python实现经典排序算法的示例代码
2021/02/07 Python
详解CSS的border边框属性及其在CSS3中的新特性
2016/05/10 HTML / CSS
HTML5注册页面示例代码
2014/03/27 HTML / CSS
日本最大级玩偶手办购物:あみあみ Amiami
2018/04/23 全球购物
全球最大的游戏市场:G2A
2018/07/05 全球购物
员工薪酬福利制度
2014/01/17 职场文书
《蜗牛的奖杯》教后反思
2014/04/24 职场文书
大学竞选班干部演讲稿
2014/08/21 职场文书
廉政教育的心得体会
2014/09/01 职场文书
2015年前台接待工作总结
2015/05/04 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
Log4j.properties配置及其使用
2021/08/02 Java/Android
国产动画《万圣街》日语配音版制作决定!
2022/03/20 国漫