精通Python自动化脚本-运维人员宝典第十六章 网络抓取 - 从网站上提取有用的信息
本章中我们将学习网页抓取的相关知识。我将还将学习Python中用于从网站上提取信息的beautifulsoup库。
本章主要涉及如下课题:
- 什么是网页抓取?
- 数据提取
- 从维基百科提取信息
什么是网页抓取?
网页抓取是一种用于从网站上提取信息的技术。这一技术用于将非结构化数据转化为结构化数据。
网页抓取的用法是从网站是提取数据。提取的数据存储在本地系统的文件中,也可以存储在数据库的数据表中。网页抓取软件使用HTTP或浏览器直接访问万维网(WWW)。这是由网页爬虫或机器人实现的自动化过程。
爬取网页包含获取页面,然后提取数据。网页爬虫获取页面。爬虫是网页抓取中不可或缺的一个组件。在获取页面之后,就需要进行提取了。我们可以对页面进行搜索、解析、保存数据到数据表以及重构页面。
数据提取
这一部分,我们来看实际的数据提取过程。Python的beautifulsoup库可执行数据提取任务。我们还将使用Python的requests库。
首先,我们应安装这两个库。运行如下命令来安装requests和beautifulsoup库:
$ pip3 install requests
$ pip3 install beautifulsoup4
requests库
requests库的用处是以可读的格式使用Python脚本中的HTTP。我们可以在Python中使用requests库下载页面。requests库有不同的请求类型。这里我们将学习GET请求。GET请求用于从web服务器获取信息。web请求下载指定网页的HTML内容。每次请求都有一个状态码。状态码返回我们向服务器发送的每次请求。这些状态码向我们表明所做请求状况的信息。状态码的类型列举如下:
- 200: 表明一切正常并在结果时返回结果
- 301: 表明在域名切换或端点(endpoint)发生变化时服务器重定向到不同的端点
- 400:表明请求有问题
- 401: 表明请求未授权
- 403: 表明在尝试访问禁止访问的资源
- 404: 表明尝试访问的资源在服务器上不存在
beautifulsoup库
beautifulsoup是一个Python库,用于网页抓取。它带有搜索、导航、变更等简单易用的方法。是一个用于从网页上提取数据的工具集。
下面,要在我们的脚本中使用beautifulsoup的功能,需要使用import语句导入这两具库。我们将来看一个解析网页的示例。这里我们来解析一个IMDb网站的热门新闻面。创建一个脚本parse_web_page.py并在其中加入如下的内容:
import requests
from bs4 import BeautifulSoup
page_result = requests.get('https://www.imdb.com/news/top?ref_=nv_nw_tp')
parse_obj = BeautifulSoup(page_result.content, 'html.parser')
print(parse_obj)
运行脚本,我们将得到如下输出:
$ python3 parse_web_page.py
# 输出结果:
<!DOCTYPE html>
<html xmlns:fb="http://www.facebook.com/2008/fbml" xmlns:og="http://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta content="app-id=342792525, app-argument=imdb:///?src=mdot" name="apple-itunes-app"/>
<script type="text/javascript">var IMDbTimer={starttime: new Date().getTime(),pt:'java'};</script>
<script>
if (typeof uet == 'function') {
uet("bb", "LoadTitle", {wb: 1});
}
</script>
...
<div id="servertime" time="33"></div>
<script>
if (typeof uet == 'function') {
uet("be");
}
</script>
</body>
</html>
上例中,我们获取了一个页面并使用beautifulsoup对其进行解析。首先我们导入了requests和beautifulsoup模块。然后,使用GET请求来获取 URL 并将该 URL 赋值给变量page_result。接着我们创建了beautifulsoup对象parse_obj。这一对象接收从requests获取的page_result.content作为参数,然后使用 html.parser对页面进行了解析。
下面我们将从class 和a标签中提取内容。要执行这一操作,打开浏览器并在想要提取的内容上右击,向下滚动可以看到Inspect(查看元素)的选项。点击它可以获取到class名。传入程序中并运行脚本。为此创建一个脚本extract_from_class.py并在其中编写如下内容:
import requests
from bs4 import BeautifulSoup
page_result = requests.get('https://www.imdb.com/news/top?ref_=nv_nw_tp')
parse_obj = BeautifulSoup(page_result.content, 'html.parser')
top_news = parse_obj.find(class_='news-article__content')
print(top_news)
运行脚本,我们将得到如下输出:
$ python3 extract_from_class.py
<div class="news-article__content">
For a second weekend in a row <a href="/company/co0008970/">Disney</a> and <a href="/company/co0051941/">Marvel</a>'s <a href="/title/tt4154664/">Captain Marvel</a> topped the weekend box office as it has now posted over $760 million worldwide in just twelve days in global release. Overall, the weekend ended up topping the same weekend last year for a second straight week as both <a href="/title/tt6428676/">Wonder Park</a> and <a href="/title/tt6472976/">Five Feet Apart</a> outperformed expectations with their opening weekend performance. At the same time <a href="/company/co0173285/">Lionsgate</a>'s release of <a href="/company/co0325194/">Pantelion</a>'s <a href="/title/tt9019352/">No Manches Frida 2</a> delivered a top ten finish from just 472 theaters, topping Focus's disappointing release of <a href="/title/tt5968394/">Captive State</a>, which struggled in its debut in over 2,500 locations. Disney's <a href="/title/tt4154664/">Captain Marvel</a> topped the weekend box office for a second weekend in a row, delivering an estimated $69.3 million sophomore frame, dipping -54.8% and outperforming the -56% average second weekend dip for a film in the Marvel Cinematic Universe. This pushes the film's domestic cume over $266 million after just ten days in domestic release.
</div>
上例中,首先我们导入了requests和beautifulsoup模块。然后,我们创建了一个请求对象并传入URL。接着,我们创建了一个beautifulsoup对象parse_obj。该对象从接收请求的page_result.content作为参数,并使用html.parser解析页面。然后我们使用了beautifulsoup的find()方法来从news-article__content这个 class中获取内容。
下面,我们来看一个从指定标签中提取内容的示例。在这个示例中,我们将从<a>
标签中提取内容。创建一个脚本extract_from_tag.py并在其中编写如下内容:
import requests
from bs4 import BeautifulSoup
page_result = requests.get('https://www.imdb.com/news/top?ref_=nv_nw_tp')
parse_obj = BeautifulSoup(page_result.content, 'html.parser')
top_news = parse_obj.find(class_='news-article__content')
top_news_a_content = top_news.find_all('a')
print(top_news_a_content)
运行脚本,我们将得到如下输出:
$ python3 extract_from_tag.py
[<a href="/company/co0008970/">Disney</a>, <a href="/company/co0051941/">Marvel</a>, <a href="/title/tt4154664/">Captain Marvel</a>, <a href="/title/tt6428676/">Wonder Park</a>, <a href="/title/tt6472976/">Five Feet Apart</a>, <a href="/company/co0173285/">Lionsgate</a>, <a href="/company/co0325194/">Pantelion</a>, <a href="/title/tt9019352/">No Manches Frida 2</a>, <a href="/title/tt5968394/">Captive State</a>, <a href="/title/tt4154664/">Captain Marvel</a>]
上例中,我们从<a>
标签中提取了内容。我们使用了find_all()方法来从news-article__content这个]()[class中提取了所有<a>
标签中的内容。
从维基百科提取信息
这一部分中,我们将来看一个从维基百科获取舞蹈形式列表的示例。我们将列出所有的传统印度舞。创建一个脚本extract_from_wikipedia.py并在其中编写如下内容:
import requests
from bs4 import BeautifulSoup
page_result = requests.get('https://en.wikipedia.org/wiki/Portal:History')
parse_obj = BeautifulSoup(page_result.content, 'html.parser')
h_obj = parse_obj.find(class_='hlist noprint')
h_obj_a_content = h_obj.find_all('a')
print(h_obj)
print(h_obj_a_content)
运行脚本,输出内容如下:
$ python3 extract_from_wikipedia.py
<div class="hlist noprint" id="portals-browsebar" style="text-align: center;">
<dl><dt><a href="/wiki/Portal:Contents/Portals" title="Portal:Contents/Portals">Portal topics</a></dt>
<dd><a href="/wiki/Portal:Contents/Portals#Human_activities" title="Portal:Contents/Portals">Activities</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Culture_and_the_arts" title="Portal:Contents/Portals">Culture</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Geography_and_places" title="Portal:Contents/Portals">Geography</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Health_and_fitness" title="Portal:Contents/Portals">Health</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#History_and_events" title="Portal:Contents/Portals">History</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Mathematics_and_logic" title="Portal:Contents/Portals">Mathematics</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Natural_and_physical_sciences" title="Portal:Contents/Portals">Nature</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#People_and_self" title="Portal:Contents/Portals">People</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Philosophy_and_thinking" title="Portal:Contents/Portals">Philosophy</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Religion_and_belief_systems" title="Portal:Contents/Portals">Religion</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Society_and_social_sciences" title="Portal:Contents/Portals">Society</a></dd>
<dd><a href="/wiki/Portal:Contents/Portals#Technology_and_applied_sciences" title="Portal:Contents/Portals">Technology</a></dd>
<dd><a href="/wiki/Special:RandomInCategory/All_portals" title="Special:RandomInCategory/All portals">Random portal</a></dd></dl>
</div>
[<a href="/wiki/Portal:Contents/Portals" title="Portal:Contents/Portals">Portal topics</a>, <a href="/wiki/Portal:Contents/Portals#Human_activities" title="Portal:Contents/Portals">Activities</a>, <a href="/wiki/Portal:Contents/Portals#Culture_and_the_arts" title="Portal:Contents/Portals">Culture</a>, <a href="/wiki/Portal:Contents/Portals#Geography_and_places" title="Portal:Contents/Portals">Geography</a>, <a href="/wiki/Portal:Contents/Portals#Health_and_fitness" title="Portal:Contents/Portals">Health</a>, <a href="/wiki/Portal:Contents/Portals#History_and_events" title="Portal:Contents/Portals">History</a>, <a href="/wiki/Portal:Contents/Portals#Mathematics_and_logic" title="Portal:Contents/Portals">Mathematics</a>, <a href="/wiki/Portal:Contents/Portals#Natural_and_physical_sciences" title="Portal:Contents/Portals">Nature</a>, <a href="/wiki/Portal:Contents/Portals#People_and_self" title="Portal:Contents/Portals">People</a>, <a href="/wiki/Portal:Contents/Portals#Philosophy_and_thinking" title="Portal:Contents/Portals">Philosophy</a>, <a href="/wiki/Portal:Contents/Portals#Religion_and_belief_systems" title="Portal:Contents/Portals">Religion</a>, <a href="/wiki/Portal:Contents/Portals#Society_and_social_sciences" title="Portal:Contents/Portals">Society</a>, <a href="/wiki/Portal:Contents/Portals#Technology_and_applied_sciences" title="Portal:Contents/Portals">Technology</a>, <a href="/wiki/Special:RandomInCategory/All_portals" title="Special:RandomInCategory/All portals">Random portal</a>]
总结
本章中,我们学习了什么是网页抓取。还学习了两个用于从网页提取数据的库。同时从维基百科上提取了信息。
下一章中,我们将学习数据的收集和报表。我们将学习NumPy模块、数据可视化以及使用图表来展示数据。
课后问题
- 什么是网页抓取?
- 什么是网页爬虫?
- 你是否能在登录页后爬取数据?
- 你是否能爬取 Twitter?
- 是否是爬取 JavaScript 页面?若可以,如何爬取?
扩展阅读
- Urllib文档:docs.python.org/3/library/u…
- Mechanize: mechanize.readthedocs.io/en/latest/
- Scrapemark: pypi.org/project/scr…
- Scrapy: doc.scrapy.org/en/latest/i…
转载自:https://juejin.cn/post/7060290820238213151