精通Python自动化脚本-运维人员宝典完整目录:
第一章 Python脚本概述
第二章 Python脚本调试和性能测试
第三章 单元测试-单元测试框架的介绍
第四章 自动化常规运维活动
第五章 文件、目录和数据处理
第六章 文件存档、加密和解密
第七章 文本处理和正则表达式
第八章 文档和报告
第九章 操作各类文件
第十章 网络基础 – Socket编程
第十一章 使用Python脚本处理邮件
第十二章 使用Telnet和SSH远程监控主机
第十三章 创建图形化用户界面
第十四章 处理Apache和其它的日志文件
第十五章 SOAP和REST API通讯
第十六章 网络抓取 – 从网站上提取有用的信息
第十七章 数据收集及报表
第十八章 MySQL和SQLite数据库管理
本章中我们将学习网页抓取的相关知识。我将还将学习Python中用于从网站上提取信息的beautifulsoup库。
本章主要涉及如下课题:
- 什么是网页抓取?
- 数据提取
- 从维基百科提取信息
什么是网页抓取?
网页抓取是一种用于从网站上提取信息的技术。这一技术用于将非结构化数据转化为结构化数据。
网页抓取的用法是从网站是提取数据。提取的数据存储在本地系统的文件中,也可以存储在数据库的数据表中。网页抓取软件使用HTTP或浏览器直接访问万维网(WWW)。这是由网页爬虫或机器人实现的自动化过程。
爬取网页包含获取页面,然后提取数据。网页爬虫获取页面。爬虫是网页抓取中不可或缺的一个组件。在获取页面之后,就需要进行提取了。我们可以对页面进行搜索、解析、保存数据到数据表以及重构页面。
数据提取
这一部分,我们来看实际的数据提取过程。Python的beautifulsoup库可执行数据提取任务。我们还将使用Python的requests库。
首先,我们应安装这两个库。运行如下命令来安装requests和beautifulsoup库:
1 2 |
$ 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并在其中加入如下的内容:
1 2 3 4 5 6 7 |
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) |
运行脚本,我们将得到如下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
$ 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并在其中编写如下内容:
1 2 3 4 5 6 7 8 |
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) |
运行脚本,我们将得到如下输出:
1 2 3 4 |
$ 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并在其中编写如下内容:
1 2 3 4 5 6 7 8 9 |
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) |
运行脚本,我们将得到如下输出:
1 2 |
$ 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并在其中编写如下内容:
1 2 3 4 5 6 7 8 9 10 11 |
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) |
运行脚本,输出内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ 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文档:https://docs.python.org/3/library/urllib.html
- Mechanize: https://mechanize.readthedocs.io/en/latest/
- Scrapemark: https://pypi.org/project/scrape/
- Scrapy: https://doc.scrapy.org/en/latest/index.html