1.开始Python中可以进行网页解析的库(图)
优采云 发布时间: 2021-08-17 02:011.开始Python中可以进行网页解析的库(图)
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库的response对象进行什么操作,这个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 获取有多少个职位
jobs = r.html.find("h1.call-to-action")
# xpath 获取
jobs = r.html.xpath("//h1[@class='call-to-action']")
方法名很简单,符合Python优雅的风格。下面简单介绍一下这两种方法:
4. CSS 简单规则5. Xpath 简单规则
定位元素后,需要获取元素中的内容和属性相关数据,获取文本:
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)
# for
智能发现和分页是通过迭代器实现的。在这个迭代器中,将使用一个名为 _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 Page 或 Load More 引导。他用这面旗帜来判断。默认情况下,它以列表的形式全局存在:['next','more','older']。我个人认为这种方法非常不灵活,几乎没有可扩展性。有兴趣的可以在github上提交代码优化。
7.加载js
现在可能考虑到一些js的异步加载,这个库支持js运行时,官方说明如下:
在 Chromium 中重新加载响应,并用更新的版本替换 HTML 内容,并执行 JavaScript。
使用非常简单,直接调用如下方法:
r.html.render()
第一次使用时,会下载Chromium,但是如果你在中国知道,请自己想办法下载,不要等它自己下载。 render函数可以使用js脚本来操作页面,滚动操作有单独的参数。这对上拉加载等新型页面非常友好。
8.总结
Reitz大神设计的东西一如既往的简单好用。我自己做的不多。大部分都是用别人的东西来组装和简化api。这真的是人类。但是,在某些地方,空间仍然得到了优化。希望有兴趣有活力的童鞋可以去github关注这个项目。