1.8request-html
全面支持解析JavaScript!
CSS 选择器 (jQuery风格, 感谢PyQuery).
XPath 选择器, for the faint at heart.
自定义user-agent (就像一个真正的web浏览器).
自动追踪重定向.
连接池与cookie持久化.
令人欣喜的请求体验,魔法般的解析页面.
接触过爬虫用的最多的包无非就是requests, urllib包,我们在使用这些包的时候显示,用requests包去获取响应,然后再利用pyquery或者bs4,xpath再去整理提取我们需要是目标数据。也就是下面两步
import requests from pyquery import PyQuery as pq #获取网页 html = requests.get() #解析网页 doc = pq(html)
但是在 request-html 里只需要一步就可以完成,而且可以直接进行 js 渲染
requests的作者Kenneth Reitz 开发的requests-html 爬虫包 是基于现有的框架 PyQuery、Requests、lxml、beautifulsoup4等库进行了二次封装,作者将Requests的简单,便捷,强大又做了一次升级。这里是github地址
安装:
pip install request-html
基本使用
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)
获取链接( links 与 absolute_links )
from requests_html import HTMLSession # 获取请求对象 session = HTMLSession() jd = session.get('https://jd.com') print(jd.html.links) # 若获取的链接中有相对路径 # 我们还可以通过 absolute_links 获取所有的绝对链接 print(jd.html.absolute_links)
CSS 选择器与 XPATH
requests-html 支持 CSS 选择器和 XPATH 两种语法选取 HTML 元素
首先先来看看CSS选择器语法,它需要使用HTML的 find 函数来查找元素。
from requests_html import HTMLSession session = HTMLSession() url = 'https://www.qiushibaike.com/text'
通过 CSS 选择器选取一个 Element 对象
css选择器语法:http://www.w3school.com.cn/cssref/css_selectors.asp
CSS选择器示例:
- a
- a.someClass
- a#someID
- a[target=_blank]
# 获取响应数据对象 obj = session.get(url) # 通过 CSS 选择器选取一个 Element 对象 # 获取 id 为 content-left 的 div 标签,标签返回一个对象 content = obj.html.find('div#content-left', first=True)
获取一个Element对象内的文本内容
content_text = content.text
获取一个 Element 对象的完整的 HTML 内容
content_html = content.html
获取一个Element对象的所有attributes
content_attrs = content.attrs
获取Element对象内的指定的所有子Element对象,返回列表
a_list = content.find('a')
循环所有的 a 标签
a_list = content.find('a') for a in a_list: try: # 获取a标签内所有属性的href属性 并拼接 href = a.attrs['href'] if href.startswith('/'): url = 'https://www.qiushibaike.com' + href print(url) except: pass
在获取的页面中通过search查找文本
{}大括号相当于正则的从头到后开始匹配,获取当中想要获取的数据
text = obj.html.search('把{}夹')[0] # 获取从 "把" 到 "夹" 字的所有内容 text = obj.html.search('把糗事{}夹')[0] # 获取从把子到夹字的所有内容 print(text)
支持 XPATH
xpath选择器语法:http://www.w3school.com.cn/xpath/index.asp
a_list = obj.html.xpath('//a') # 获取 html 内所有的 a 标签 for a in a_list: try: href = a.attrs['href'] # 若是// 开头的 url 都扔掉 if href.startswith('//'): continue elif href.startswith('/'): print('https://www.qiushibaike.com' + href) except: pass
获取到只包含某些文本的Element对象(containing)
# 获取所有文本内容为幽默笑话大全_爆笑笑话_笑破你的肚子的搞笑段子 - 糗事百科 title标签 # 注意: 文本内有空格也必须把空格带上 title = obj.html.find('div', containing='后来') print(title[0].text)
支持 JavaScript
下面就是重磅炸弹了!!!高能预警!!!
注意,当你第一次调用render()方法时,代码将会自动下载Chromium,并保存在你的家目录下(如:~/.pyppeteer/)。它只会下载这一次。
from requests_html import HTMLSession session = HTMLSession() res = session.get('https://piaofang.maoyan.com/dashboard') res.html.render() print(res.text)
render函数还有一些参数,介绍一下(这些参数有的还有默认值,直接看源代码方法参数列表即可):
- retries: 加载页面失败的次数
- script: 页面上需要执行的JS脚本(可选)
- wait: 加载页面钱的等待时间(秒),防止超时(可选)
- scrolldown: 页面向下滚动的次数
- sleep: 在页面初次渲染之后的等待时间
- reload: 如果为假,那么页面不会从浏览器中加载,而是从内存中加载
- keep_page: 如果为真,允许你用r.html.page访问页面
如果
scrolldown
和sleep
都指定,那么程序会在暂停相应时间后,再往后翻页面(如:scrolldown=10, sleep=1
)如果仅指定了
sleep
,程序会暂停相应时间,再返回数据如果指定
script
,他将会在运行时执行提供的JavaScript。如:script = """ () => { return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight, deviceScaleFactor: window.devicePixelRatio, } } """
返回一段JavaScript的返回值:
>>> r.html.render(script=script) {'width': 800, 'height': 600, 'deviceScaleFactor': 1}
自定义 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))
模拟表单提交(POST)
HTMLSession 封装了一整套的HTTP方法,包括get、post、delete等, 对应HTTP中各个方法。
# 表单登录 res = session.post('http://httpbin.org/post', data={'username': 'santa', 'password': '123'}) pprint(json.loads(res.html.html)) ''' # 打印结果 {'args': {}, 'data': '', 'files': {}, 'form': {'password': '123', 'username': 'santa'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '27', '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', 'X-Amzn-Trace-Id': 'Root=1-5e40d021-0261ed6c9fbc7df0daf90e98'}, 'json': None, 'origin': '117.153.8.82', 'url': 'http://httpbin.org/post'} '''
async异步使用
requests-html内部就封装好了aynsc异步请求的功能,可以提高我们的爬虫效率
# 使用异步发送请求 async_session = AsyncHTMLSession() ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" async def get_taobao(): url = 'https://www.taobao.com/' res = await async_session.get(url, headers={'user-agent': ua}) # print(res.html.links) return res.html.xpath("//head/title/text()")[0] async def get_jd(): url = 'https://www.jd.com/' res = await async_session.get(url) # print(res.html.absolute_links) return res.html.xpath("//head/title/text()")[0] start_time = time.time() res = async_session.run(get_taobao, get_jd) print(res) print(time.time()-start_time) # 同步发送请求 session = HTMLSession() start_time = time.time() res = session.get('https://www.jd.com') print(res.html.links) res = session.get('https://www.taobao.com') print(res.html.absolute_links) print('fd ',time.time()-start_time)