BeautifulSoup 已过时:2020 年的网络抓取
1. 无依赖
2. 包含电池
4. 从原型设计到生产
5. 符合 PEP 561
6.自动格式化
7.速度
8.部分匹配
9. 无债一身轻
10.开放(且友好)!
BeautifulSoup ( bs4
) 创建于十五年前,自那时起就一直是网络数据抓取的标准bs4
。但现在是时候推出一些新东西了,因为它已经过时了。
在这篇文章中,我们将通过抓取这篇文章的部分内容来探讨为什么西班牙凉菜汤是网络抓取的未来!
1. 无依赖
gazpacho
在命令行安装:
pip install gazpacho
没有额外的依赖:
pip freeze
# gazpacho==1.1
相比之下,与和bs4
打包在一起。我不会告诉你如何编写软件,但最小化依赖关系通常是一个好主意……soupsieve
lxml
2. 包含电池
可以使用以下命令获取并解析此博客文章的 html Soup.get
:
from gazpacho import Soup
url = "https://dev.to/maxhumber/beautifulsoup-is-so-2000-and-late-web-scraping-in-2020-2528"
soup = Soup.get(url)
不幸的是,你需要requests
做bs4
同样的事情:
import requests
from bs4 import BeautifulSoup
url = "https://dev.to/maxhumber/beautifulsoup-is-so-2000-and-late-web-scraping-in-2020-2528"
html = requests.get(url).text
bsoup = BeautifulSoup(html)
3.find
简单
bs4
简直是庞然大物。每个对象都绑定了184 个BeautifulSoup
方法和属性。这让人很难知道该用什么,以及何时该用:
len(dir(BeautifulSoup()))
# 184
相比之下,Soup
中的对象gazpacho
很简单;只有七种方法和属性需要跟踪:
[method for method in dir(Soup())]
# ['attrs', 'find', 'get', 'html', 'strip', 'tag', 'text']
查看该列表可以清楚地看出,例如,要找到该帖子的标题(嵌套在h1
标签内),我们需要使用.find
:
soup.find('h1')
4. 从原型设计到生产
gazpacho
非常适合原型设计,甚至更适合生产环境。默认情况下,如果只找到一个元素,.find
则返回一个对象;如果找到多个元素,Soup
则返回一个对象列表。Soup
为了在生产中保证和强制返回类型,可以手动设置mode=
参数:.find
title = (soup
.find("header", {'id': 'main-title'}, mode="first")
.find("h1", mode="all")[0]
.text
)
相比之下,bs4
有27 种查找方法,它们都返回不同的结果:
[method for method in dir(BeautifulSoup()) if 'find' in method]
5. 符合 PEP 561
从1.1 版开始,gazpacho
它符合PEP 561标准。这意味着整个库都是类型化的,并且可以与您的类型化(或标准鸭子/非类型化!)代码库兼容:
help(soup.find)
# Signature:
# soup.find(
# tag: str,
# attrs: Union[Dict[str, Any], NoneType] = None,
# *,
# partial: bool = True,
# mode: str = 'automatic',
# strict: Union[bool, NoneType] = None,
# ) -> Union[List[ForwardRef('Soup')], ForwardRef('Soup'), NoneType]
6.自动格式化
dev.to和这篇文章的 html格式都很好。但如果格式不对:
header = soup.find("div", {'class': 'crayons-article__header__meta'})
html = str(header.find("div", {'class': 'mb-4 spec__tags'}))
bad_html = html.replace("\n", "") # remove new line characters
print(bad_html)
# <div class="mb-4 spec__tags"> <a class="crayons-tag mr-1" href="/t/python" style="background-color:#1E38BB;color:#FFDF5B"> <span class="crayons-tag__prefix">#</span> python </a> <a class="crayons-tag mr-1" href="/t/webscraping" style="background-color:;color:"> <span class="crayons-tag__prefix">#</span> webscraping </a> <a class="crayons-tag mr-1" href="/t/gazpacho" style="background-color:;color:"> <span class="crayons-tag__prefix">#</span> gazpacho </a> <a class="crayons-tag mr-1" href="/t/hacktoberfest" style="background-color:#29161f;color:#ffa368"> <span class="crayons-tag__prefix">#</span> hacktoberfest </a></div>
gazpacho
能够自动格式化和缩进错误/格式错误的 html:
tags = Soup(bad_html)
让内容更容易阅读:
print(tags)
# <div class="mb-4 spec__tags">
# <a class="crayons-tag mr-1" href="/t/python" style="background-color:#1E38BB;color:#FFDF5B">
# <span class="crayons-tag__prefix">#</span>
# python
# </a>
# <a class="crayons-tag mr-1" href="/t/webscraping" style="background-color:;color:">
# <span class="crayons-tag__prefix">#</span>
# webscraping
# </a>
# <a class="crayons-tag mr-1" href="/t/gazpacho" style="background-color:;color:">
# <span class="crayons-tag__prefix">#</span>
# gazpacho
# </a>
# <a class="crayons-tag mr-1" href="/t/hacktoberfest" style="background-color:#29161f;color:#ffa368">
# <span class="crayons-tag__prefix">#</span>
# hacktoberfest
# </a>
# </div>
7.速度
gazpacho
速度很快。抓取此帖子的标签链接仅需 258 微秒:
%%timeit
tags = Soup(bad_html)
tags = tags.find("a")
tag_links = ["https://dev.to" + tag.attrs['href'] for tag in tags]
# 258 µs ± 10.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
而bs4
做同样的事情却要花几乎两倍的时间:
%%timeit
tags = BeautifulSoup(bad_html)
tags = tags.find_all("a")
tag_links = ["https://dev.to" + tag.attrs['href'] for tag in tags]
# 465 µs ± 2.61 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
8.部分匹配
gazpacho
可以部分匹配 HTML 元素属性。例如,此页面的侧边栏显示如下 HTML 代码:
<aside class="crayons-layout__sidebar-right" aria-label="Right sidebar navigation">
并且可以精确匹配:
soup.find("aside", {"class": "crayons-layout__sidebar-right"}, partial=False)
或者部分(默认行为)使用:
sidebar = soup.find("aside", {'aria-label': 'Right sidebar'}, partial=True)
# finding my name
sidebar.find("span", {'class': 'crayons-subtitle-2'}, partial=True).text
9. 无债一身轻
gazpacho 首先是 Python 3 的Black 版本,使用mypy进行类型转换,sloc 大约为 400。阅读源代码很容易:
import inspect
source = inspect.getsource(Soup.find)
print(source)
并且似乎bs4
没有充斥着Python 2 技术债务。
10.开放(且友好)!
最重要的是,gazpacho
它是开源的,托管在GitHub上(而不是一些笨重的自定义平台)并正在寻找贡献者。
如果你要参加 #hacktoberfest,我们非常欢迎你。有几个未解决的问题需要帮助!
鏂囩珷鏉ユ簮锛�https://dev.to/maxhumer/beautifulsoup-is-so-2000-and-late-web-scraping-in-2020-2528