requests-html 库初识 + 无资料解 BUG 之 I/O error : encoder error,Python 爬虫第 30 例
本篇博客是《爬虫 120 例》的第 30 例,新学习一个爬虫框架 requests-html
,该框架作者就是 requests
的作者,所以盲猜就很好用啦。
知识铺垫工作
requests-html
模块安装使用 pip install requests-html
即可,官方手册查询地址:https://requests-html.kennethreitz.org/,官方并没有直接的中文翻译,在检索过程中,确实发现了一版中文手册,在文末提供。
先看一下官方对该库的基本描述:
Full JavaScript support!(完全支持 JS,这里手册还重点标记了一下,初学阶段可以先忽略)
CSS Selectors (a.k.a jQuery-style, thanks to PyQuery).(集成了 pyquery 库,支持 css 选择器)
XPath Selectors, for the faint at heart.(支持 XPath 选择器)
Mocked user-agent (like a real web browser).(mock UA 数据,这点不错)
Automatic following of redirects.(自动跟踪重定向)
Connection–pooling and cookie persistence.(持久性 COOKIE)
The Requests experience you know and love, with magical parsing abilities.(额,这最后一点,各位自己领悟吧)
Only Python 3.6 is supported. 仅支持 Python 3.6 ,实测发现 3.6 以上版本依旧可以。
对于该库的简单使用,代码如下所示:
首先从 requests_html
库导入 HTMLSession
类,然后将其实例化之后,调用其 get
方法,发送请求,得到的 r
输出为 <Response [200]>
,后续即可使用内置的解析库对数据进行解析。
由于该库是解析 html
对象,所以可以查看对应的 html
对象包含哪些方法与与属性。
通过 dir
函数查阅。
该函数只能输入大概内容,细节还是需要通过 help 函数查询,例如:
html 对象的方法包括
find
:提供一个 css 选择器,返回一个元素列表;xpath
:提供一个 xpath 表达式,返回一个元素列表;search
: 根据传入的模板参数,查找 Element 对象;search_all
:同上,返回的全部数据;
html 对象的属性包括
links
:返回页面所有链接;absolute_links
:返回页面所有链接的绝对地址;base_url
:页面的基准 URL;html
,raw_html
,text
:以 HTML 格式输入页面,输出未解析过的网页,提取页面所有文本;
有了上述内容铺垫之后,在进行 Python 爬虫的编写就会变的容易许多,requests-html
库将通过 3~4 个案例进行学习掌握,接下来进入第一个案例。
目标站点分析
本次要采集的目标网站为:http://www.world68.com/top.asp?t=5star&page=1,目标站点描述为【全球名站】。
在获取数据源发送请求前,忽然想起可以动态修改 user-agent
,查阅该库源码发现,它只是使用了 fake_useragent
库来进行操作,并无太神奇的地方,所以可用可不用该内容。
其余内容相对比较简单,页码规则如下:
累计页数直接在底部进行了展示,可以设计为用户手动输入,即 input
函数实现。
目标数据存储网站名与网站地址即可,基于此,开始编码。
编码时间
首先通过单线程实现 requests-html
的基本逻辑,注意到下述代码非常轻量,
上述代码重点部分说明如下:
world.encoding
,设置了网页解析编码;world.html.find('dl>dt>a')
通过 css 选择器,查找所有的网页标题元素;item.text
提取网页标题内容;item.attrs['href']
获取元素属性,即网站域名。
运行效果如下所示,获取到的 3519
个站点,就不在提供了,简单运行 1 分钟代码,即可得到。
由于上述代码太少了,完全不够今日代码量,我们顺手将其修改为多线程形式。
在正式进行编码之后,发现存在比较大的问题,编码问题,出现如下错误:
该错误在执行单线程时并未发生,但是当执行多线程时,异常开始出现,本问题在互联网上无解决方案,只能自行通过 requests-html
库的源码进行修改。
打开 requests_html.py
文件,将 417 行左右的代码进行如下修改:
代码 if isinstance(html, str):
用于判断 html
是否为 str
,但是在实测过程中发现 html
是 <class 'bytes'>
类型,所以数据没有进行转码工作,故取消相关判断。
除此以外,通过输出 world.html.encoding
发现网页的编码不是 GB2312
,而是 gb18030
,所以通过下述代码进行了默认编码的设置。
按照如上内容进行修改之后,代码可以正常运行,数据能正确的采集到。
本案例还新增了代码运行时长的计算,具体如下:
完整的代码运行效果如下所示:
收藏时间
代码仓库地址:https://codechina.csdn.net/hihell/python120,去给个关注或者 Star 吧。
数据没有采集完毕,想要的可以在评论区留言交流
版权声明: 本文为 InfoQ 作者【梦想橡皮擦】的原创文章。
原文链接:【http://xie.infoq.cn/article/fd9aafcbac5d13c0b4fa19054】。文章转载请联系作者。
评论