Python网络爬虫权威指南(第2版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-10-03 10:46:12

点击下载

作者:(美) 瑞安·米切尔(Ryan Mitchell)

出版社:人民邮电出版社有限公司

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python网络爬虫权威指南(第2版)

Python网络爬虫权威指南(第2版)试读:

前言

什么是网页抓取

为什么要做网页抓取

关于本书

排版约定

使用代码示例

O'Reilly Safari

联系我们

致谢

电子书

第一部分 创建爬虫第 1 章 初见网络爬虫

1.1 网络连接

1.2 BeautifulSoup简介1.2.1 安装BeautifulSoup1.2.2 运行BeautifulSoup1.2.3 可靠的网络连接以及异常的处理第 2 章 复杂 HTML 解析

2.1 不是一直都要用锤子

2.2 再端一碗BeautifulSoup2.2.1 BeautifulSoup的find()和find_all()2.2.2 其他BeautifulSoup对象2.2.3 导航树

2.3 正则表达式

2.4 正则表达式和BeautifulSoup

2.5 获取属性

2.6 Lambda表达式第 3 章 编写网络爬虫

3.1 遍历单个域名

3.2 抓取整个网站收集整个网站的数据

3.3 在互联网上抓取收集在网站上发现的所有外链列表 allExtLinks = set()第 4 章 网络爬虫模型

4.1 规划和定义对象

4.2 处理不同的网站布局

4.3 结构化爬虫4.3.1 通过搜索抓取网站4.3.2 通过链接抓取网站4.3.3 抓取多种类型的页面

4.4 关于网络爬虫模型的思考第 5 章 Scrapy

5.1 安装Scrapy蜘蛛初始化

5.2 创建一个简易爬虫

5.3 带规则的抓取

5.4 创建item

5.5 输出item

5.6 item管线组件

5.7 Scrapy日志管理

5.8 更多资源第 6 章 存储数据

6.1 媒体文件

6.2 把数据存储到CSV

6.3 MySQL6.3.1 安装MySQL6.3.2 基本命令6.3.3 与Python整合6.3.4 数据库技术与最佳实践6.3.5 MySQL里的“六度空间游戏”

6.4 Email第二部分 高级网页抓取第 7 章 读取文档

7.1 文档编码

7.2 纯文本文本编码和全球互联网

7.3 CSV读取CSV文件

7.4 PDF

7.5 微软Word和.docx第 8 章 数据清洗

8.1 编写代码清洗数据数据标准化

8.2 数据存储后再清洗OpenRefine第 9 章 自然语言处理

9.1 概括数据

9.2 马尔可夫模型维基百科六度分隔:终结篇

9.3 自然语言工具包9.3.1 安装与设置9.3.2 用NLTK做统计分析9.3.3 用NLTK做词性分析

9.4 其他资源第 10 章 穿越网页表单与登录窗口进行抓取

10.1 Python Requests库

10.2 提交一个基本表单

10.3 单选按钮、复选框和其他输入

10.4 提交文件和图像

10.5 处理登录和cookieHTTP基本接入认证

10.6 其他表单问题第 11 章 抓取 JavaScript

11.1 JavaScript简介常用JavaScript库

11.2 Ajax和动态HTML11.2.1 在Python中用Selenium执行JavaScript11.2.2 Selenium的其他webdriver

11.3 处理重定向

11.4 关于JavaScript的最后提醒第 12 章 利用 API 抓取数据

12.1 API概述12.1.1 HTTP方法和API12.1.2 更多关于API响应的介绍

12.2 解析JSON数据

12.3 无文档的API12.3.1 查找无文档的API12.3.2 记录未被记录的API12.3.3 自动查找和记录API

12.4 API与其他数据源结合

12.5 再说一点API第 13 章 图像识别与文字处理

13.1 OCR库概述13.1.1 Pillow13.1.2 Tesseract13.1.3 NumPy

13.2 处理格式规范的文字13.2.1 自动调整图像13.2.2 从网站图片中抓取文字

13.3 读取验证码与训练Tesseract训练Tesseract

13.4 获取验证码并提交答案第 14 章 避开抓取陷阱

14.1 道德规范

14.2 让网络机器人看着像人类用户14.2.1 修改请求头14.2.2 用JavaScript处理cookie14.2.3 时间就是一切

14.3 常见表单安全措施14.3.1 隐含输入字段值14.3.2 避免蜜罐

14.4 问题检查表第 15 章 用爬虫测试网站

15.1 测试简介什么是单元测试

15.2 Python单元测试测试维基百科

15.3 Selenium单元测试与网站进行交互

15.4 单元测试与Selenium单元测试的选择第 16 章 并行网页抓取

16.1 进程与线程

16.2 多线程抓取16.2.1 竞争条件与队列16.2.2 threading模块

16.3 多进程抓取16.3.1 多进程抓取16.3.2 进程间通信

16.4 多进程抓取的另一种方法第 17 章 远程抓取

17.1 为什么要用远程服务器17.1.1 避免IP地址被封杀17.1.2 移植性与扩展性

17.2 Tor代理服务器PySocks

17.3 远程主机17.3.1 从网站主机运行17.3.2 从云主机运行

17.4 其他资源第 18 章 网页抓取的法律与道德约束

18.1 商标、版权、专利版权法

18.2 侵害动产

18.3 计算机欺诈与滥用法

18.4 robots.txt和服务协议

18.5 3个网络爬虫18.5.1 eBay起诉Bidder's Edge侵害其动产18.5.2 美国政府起诉Auernheimer与《计算机欺诈与滥用法》18.5.3 Field起诉Google:版权和robots.txt

18.6 勇往直前关于作者关于封面版权声明© 2018 by Ryan Mitchell.Simplified Chinese Edition, jointly published by O'Reilly Media, Inc. and Posts & Telecom Press, 2019. Authorized translation of the English edition, 2018 O'Reilly Media, Inc., the owner of all rights to publish and sell the same.All rights reserved including the rights of reproduction in whole or in part in any form.英文原版由 O'Reilly Media, Inc. 出版,2018。简体中文版由人民邮电出版社出版,2019。英文原版的翻译得到 O'Reilly Media, Inc. 的授权。此简体中文版的出版和销售得到出版权和销售权的所有者——O'Reilly Media, Inc. 的许可。版权所有,未得书面许可,本书的任何部分和全部不得以任何形式重制。

O'Reilly Media, Inc. 介绍

O'Reilly Media 通过图书、杂志、在线服务、调查研究和会议等方式传播创新知识。自 1978 年开始,O'Reilly 一直都是前沿发展的见证者和推动者。超级极客们正在开创着未来,而我们关注真正重要的技术趋势——通过放大那些“细微的信号”来刺激社会对新科技的应用。作为技术社区中活跃的参与者,O'Reilly 的发展充满了对创新的倡导、创造和发扬光大。O'Reilly 为软件开发人员带来革命性的“动物书”;创建第一个商业网站(GNN);组织了影响深远的开放源代码峰会,以至于开源软件运动以此命名;创立了 Make 杂志,从而成为 DIY 革命的主要先锋;公司一如既往地通过多种形式缔结信息与人的纽带。O'Reilly 的会议和峰会集聚了众多超级极客和高瞻远瞩的商业领袖,共同描绘出开创新产业的革命性思想。作为技术人士获取信息的选择,O'Reilly 现在还将先锋专家的知识传递给普通的计算机用户。无论是通过书籍出版、在线服务还是面授课程,每一项 O'Reilly 的产品都反映了公司不可动摇的理念——信息是激发创新的力量。

业界评论

“O'Reilly Radar 博客有口皆碑。”——Wired“O'Reilly 凭借一系列非凡想法(真希望当初我也想到了)建立了数百万美元的业务。”——Business 2.0“O'Reilly Conference 是聚集关键思想领袖的绝对典范。”——CRN“一本 O'Reilly 的书就代表一个有用、有前途、需要学习的主题。”——Irish Times“Tim 是位特立独行的商人,他不光放眼于最长远、最广阔的视野,并且切实地按照 Yogi Berra 的建议去做了:‘如果你在路上遇到岔路口,走小路(岔路)。’回顾过去,Tim 似乎每一次都选择了小路,而且有几次都是一闪即逝的机会,尽管大路也不错。”——Linux Journal

前言

对那些没有学过编程的人来说,计算机编程看着就像变魔术。如果编程是魔术(magic),那么网页抓取(Web scraping)就是巫术(wizardry),也就是运用“魔术”来实现精彩实用却又不费吹灰之力的“壮举”。在我的软件工程师职业生涯中,我几乎没有发现像网页抓取这样的编程实践,可以同时吸引程序员和门外汉的注意。虽然写一个简单的网络爬虫并不难,就是先收集数据,再显示到命令行或者存储到数据库里,但是无论你之前已经做过多少次了,这件事永远会让你感到兴奋,同时又有新的可能。不过遗憾的是,当和别的程序员提起网页抓取时,我听到了很多关于这件事的误解与困惑。有些人不确定它是不是合法的(其实合法),有些人不明白怎么处理包含大量 JavaScript 的页面以及如何处理登录问题。很多人困惑于如何开始一个大的网页抓取项目,甚至是到哪里寻找他们需要的数据。本书致力于解决人们关于网页抓取的诸多常见问题,廓清一些误解,并对常见的网页抓取任务提供全面的指导。网页抓取是一个复杂多变的领域,我会通过介绍高级概念以及详细的示例来尽可能地覆盖你可能会在数据抓取项目中遇到的情形。本书提供了代码示例来演示书中的概念,你可以尝试运行它们来实践。这些代码示例是开源的,无论注明出处与否都可以免费使用(但若注明,作者会感激不尽)。所有的代码示例都在 GitHub 网站上(https://github.com/REMitchell/python-scraping),可以查看和下载。什么是网页抓取在互联网上进行自动数据抓取这件事和互联网存在的时间差不多一样长。虽然网页抓取并不是新术语,但是多年以来,这件事更常见的称谓是网页抓屏(screen scraping)、数据挖掘(data mining)、网页收割(Web harvesting)或其他类似的版本。今天大众好像更倾向于用“网页抓取”,因此我在本书中使用这个术语,不过我倾向于把遍历多个页面的程序称作网络爬虫(Web crawler),或者把网页抓取程序称为网络机器人(bot)。理论上,网页抓取是一种通过多种手段收集网络数据的方式,不光是通过与 API 交互(或者直接与浏览器交互)的方式。最常用的方法是写一个自动化程序向网络服务器请求数据(通常是用 HTML 表单或其他网页文件),然后对数据进行解析,提取需要的信息。实践中,网页抓取涉及非常广泛的编程技术和手段,比如数据分析、自然语言解析和信息安全等。本书将在第一部分介绍关于网页抓取和网页爬取(crawling)的基础知识,一些高级主题放在第二部分介绍。我建议所有读者仔细学习第一部分,并根据自己的实际需求深入探索第二部分。为什么要做网页抓取如果你上网的唯一方式就是用浏览器,那么你其实错过了很多种可能。虽然浏览器可以更方便地执行 JavaScript、显示图片,并且可以以更适合人类阅读的形式展示数据,但是网络爬虫收集和处理大量数据的能力更为卓越。不像狭窄的显示器窗口一次只能让你看一个网页,网络爬虫可以让你一次查看几千甚至几百万个网页。另外,网络爬虫可以完成传统搜索引擎不能做的事情。用 Google 搜索“飞往波士顿最便宜的航班”,看到的是大量的广告和主流的航班搜索网站。Google 只知道这些网站的网页会显示什么内容,并不知道在航班搜索应用中输入的各种查询的准确结果。但是,设计较好的网络爬虫可以通过抓取大量的网站数据,绘制出飞往波士顿的航班价格随时间变化的图表,告诉你买机票的最佳时间。你可能会问:“数据不是可以通过 API 获取吗?”(如果你不熟悉 API,请阅读第 12 章。)确实,如果你能找到一个可以解决问题的 API,那会非常给力。它可以非常方便地从一个计算机程序向另一个计算机程序提供格式完好的数据。对于很多类型的数据都可以找到一个 API,比如推文或者维基百科页面。通常,如果有 API 可用,用 API 来获取数据确实比写一个网络爬虫程序更加方便。但是,很多时候你需要的 API 并不存在或者不适用于你的需求,这是因为:● 你要收集的数据来自不同的网站,没有一个综合多个网站数据

的 API;● 你想要的数据非常小众或不常见,网站不会为你单独创建一个

API;● 网站没有基础设施或技术能力去创建 API;● 数据很宝贵 / 被保护起来,不希望广泛传播。即使 API 已经存在,可能还会有请求内容和次数的限制,API 能够提供的数据类型或者数据格式可能也无法满足你的需求。这时网页抓取就派上用场了。你在浏览器上看到的内容,大部分都可以通过编写 Python 程序来获取。如果你可以通过程序获取数据,那么就可以把数据存储到数据库里。如果你可以把数据存储到数据库里,自然也就可以将这些数据可视化。显然,大量的应用场景都会需要这种几乎可以毫无阻碍地获取数据的手段:市场预测、机器语言翻译,甚至医疗诊断领域,通过对新闻网站、文章以及健康论坛中的数据进行抓取和分析,也可以获得很多好处。甚至在艺术领域,网页抓取也为艺术创作开辟了新方向。由 Jonathan Harris 和 Sep Kamvar 在 2006 年发起的“我们感觉挺好”(We Feel Fine)项目,从大量英文博客中抓取以“I feel”和“I am feeling”开头的短句,最终做成了一个很受大众欢迎的数据可视图,描述了这个世界每天、每分钟的感觉。无论你现在处于哪个领域,网页抓取都可以让你的工作更高效,帮你提升生产力,甚至开创一个全新的领域。关于本书本书不仅介绍了网页抓取,也为抓取、转换和使用新式网络中各种类型的数据提供了全面的指导。虽然本书用的是 Python 编程语言,涉及 Python 的许多基础知识,但这并不是一本 Python 入门书。如果你完全不了解 Python,那么这本书看起来可能有点儿费劲。请不要将本书用作 Python 的入门书。我尽量按照初、中级 Python 编程水平来编写书中的概念和代码示例,以便让更广泛的读者可以轻松地理解本书。但书中偶尔会包含一些更高级的 Python 编程知识以及一些常见的计算机科学话题。如果你是一位编程高手,那么你可以跳过书中相应的内容。如果你想更全面地学习 Python,Bill Lubanovic 写的《Python 语言及1其应用》 是本非常好的教材,只是书有点儿厚。如果不想看书,Jessica McKellar 的教学视频 Introduction to Python 也非常不错。我也非常喜欢我的前教授 Allen Downey 写的《像计算机科学家一样思考 Python》,这本书非常适合编程新手,介绍了计算机科学和软件工程的概念,以及 Python 语言。1中文版已经由人民邮电出版社出版,详见 www.ituring.com.cn/book/1560。——编者注技术书通常仅仅专注于一种语言或者一种技术,但是网页抓取是一个相当分散的主题,在实践中会涉及数据库、网络服务器、HTTP 协议、HTML 语言、网络安全、图像处理、数据科学等内容。本书试图从“数据收集”的角度涵盖所有这些内容以及其他话题。当然,本书不会对这些主题做完整的介绍,但是我相信对于入门编写网络爬虫来说足够了。第一部分深入讲解网页抓取和网页爬取相关内容,并重点介绍全书都要用到的几个 Python 库。可以将这部分内容用作这些库和技术的综合参考(对于一些特殊情形,后面会提供其他参考资料)。这部分内容对于所有编写网络爬虫的人来说都是实用的,不管网络爬虫的目标或者应用场景如何。第二部分介绍读者在动手编写网络爬虫的过程中可能会觉得有用的一些主题。不过,这些主题可能并不总是适合所有的爬虫。这些主题的范围特别广泛,无法在一章中道尽玄机。因此,文中提供了许多参考资料来方便读者获取更多的信息。本书结构清晰,你可直接跳到感兴趣的章节中阅读所需的网页抓取技术。如果一个概念或一段代码在之前的章节中出现过,那么我会明确标注出具体的位置。排版约定本书使用了下列排版约定。● 黑体字

表示新术语或重点强调的内容。● 等宽字体(constant width)

表示程序片段,以及正文中出现的变量、函数名、数据库、数据

类型、环境变量、语句和关键字等。● 加粗等宽字体(constant width bold)

表示应该由用户输入的命令或其他文本。● 斜体等宽字体(constant width italic)

表示应该由用户输入的值或根据上下文确定的值替换的文本。 该图标表示一般性说明。  该图标表示提示或建议。  该图标表示警告或警示。使用代码示例补充材料(代码示例、练习等)可以从 https://github.com/REMitchell/python-scraping 下载。本书是要帮你完成工作的。一般来说,如果书中提供了示例代码,你可以把它用在你的程序或文档中。除非你使用了很大一部分代码,否则无须联系我们获得许可。比如,用书中的几个代码片段写一个程序无须获得许可,销售或分发 O'Reilly 图书的示例光盘则需要获得许可;引用书中的示例代码回答问题无须获得许可,将书中大量的代码放到你的产品文档中则需要获得许可。我们很希望但并不强制要求你在引用本书内容时加上引用说明。引用说明一般包括书名、作者、出版社和 ISBN。比如:“Web Scraping with Python, Second Edition by Ryan Mitchell (O'Reilly). Copyright 2018 Ryan Mitchell, 978-1-491-998557-1.”如果你觉得自己对示例代码的用法超出了上述许可的范围,欢迎你通过 permissions@oreilly.com 与我们联系。遗憾的是,纸质书很难保持更新。对于网页抓取来说这更是一个挑战,由于本书用到的很多库、网站以及代码可能偶尔会被修改,所以我们的代码示例可能会运行失败或产生意想不到的结果。如果你需要运行代码示例,请从 GitHub 仓库获取代码并运行,而不是从书中直接复制。我和为本书做贡献的读者(可能也包括你)将尽量及时更新 GitHub 仓库的内容。除了代码示例,书中还提供了用于演示如何安装和运行软件的终端命令。一般来说,这些命令是适用于 Linux 操作系统的,但是通常也适用于拥有正确配置的 Python 环境并安装了 pip 的 Windows 用户。如果无法运行这些终端命令,我提供了针对所有主流操作系统的命令运行说明,并为 Windows 用户提供了一些外部的参考资料。O'Reilly SafariSafari(之前称作 Safari Books Online)是一个针对企业、政府、教育者和个人的会员制培训和参考平台。会员可以访问来自 250 多家出版商的上千种图书、培训视频、学习路径、互动式教程和精选播放列表,这些出版商包括 O'Reilly Media、Harvard Business Review、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Adobe、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett、Course Technology 等。要了解更多信息,可以访问 http://www.oreilly.com/safari。联系我们请把对本书的评价和问题发给出版社。美国:  O'Reilly Media, Inc.  1005 Gravenstein Highway North  Sebastopol, CA 95472中国:  北京市西城区西直门南大街 2 号成铭大厦 C 座 807 室(100035)  奥莱利技术咨询(北京)有限公司O'Reilly 的每一本书都有专属网页,你可以在那儿找到本书的相关信息,包括勘误表、示例代码以及其他信息。本书的网站地址是:http://shop.oreilly.com/product/0636920078067.do。对于本书的评论和技术性问题,请发送电子邮件到:bookquestions@oreilly.com。要了解更多 O'Reilly 图书、培训课程、会议和新闻的信息,请访问以下网站:  http://www.oreilly.com。我们在 Facebook 的地址如下:http://facebook.com/oreilly。请关注我们的 Twitter 动态:http://twitter.com/oreillymedia。我们的 YouTube 视频地址如下:http://www.youtube.com/oreillymedia。致谢和那些基于海量用户反馈诞生的优秀产品一样,如果没有许多协作者、支持者和编辑的帮助,本书可能永远都不会出版。首先要感谢 O'Reilly 团队对这个小众主题图书的大力支持,感谢我的朋友和家人阅读初稿并提出宝贵的建议,还要感谢和我一起在 HedgeServ 奋战的同事们帮我分担了很多工作。尤其要感谢 Allyson MacDonald、Brian Anderson、Miguel Grinberg 和 Eric VanWyk 的建议、指导和偶尔的爱之深责之切。有一些章节和代码示例是根据他们的建议写成的。还要感谢 Yale Specht 过去 4 年中在本书两个版本上的无尽耐心,他在最初便鼓励我从事这个项目,并在我的写作过程中对文体提出了宝贵的建议。没有他,这本书可能只用一半时间就能写完,但是不会像现在这么实用。最后,要感谢 Jim Waldo,是他许多年前给一个小孩邮寄了一个 Linux 机箱和 The Art and Science of C 那本书,帮她开启了计算机世界的大门。电子书扫描如下二维码,即可购买本书电子版。第一部分 创建爬虫本书第一部分重点介绍网页抓取的基本原理:如何用 Python 从网络服务器请求信息,如何对服务器的响应进行基本处理,以及如何以自动化方式与网站交互。最终,你将轻松游弋于网络空间,创建出具有域名切换、信息收集以及信息存储功能的爬虫。说实话,如果你想以较少的预先投入获取较高的回报,网页抓取肯定是一个值得踏入的神奇领域。大体上,你遇到的 90% 的网页抓取项目使用的都是接下来的 6 章里介绍的技术。这部分内容涵盖了一般人(也包括技术达人)在思考“网络爬虫”时通常的想法:● 通过网站域名获取 HTML 数据● 解析数据,获取目标信息● 存储目标信息● 如果有必要,移动到另一个网页重复这个过程这将为你学习本书第二部分中更复杂的项目奠定坚实的基础。不要天真地认为这部分内容没有第二部分里的一些比较高级的项目重要。其实,当你写自己的网络爬虫时,几乎每天都要用到第一部分的所有内容。第 1 章 初见网络爬虫一旦你开始抓取网页,就会感受到浏览器为我们做的所有细节。网页上如果没有 HTML 文本格式层、CSS 样式层、JavaScript 执行层和图像渲染层,乍看起来会有点儿吓人,但是在这一章和下一章中,我们将介绍如何在不借助浏览器帮助的情况下格式化和理解数据。本章将首先向网络服务器发送 GET 请求(获取网页内容的请求)以获取具体网页,再从网页中读取 HTML 内容,最后做一些简单的信息提取,将我们要寻找的内容分离出来。1.1 网络连接如果你没在网络或网络安全上花过太多时间,那么互联网的原理可能看起来有点儿神秘。准确地说,每当打开浏览器连接 http://google.com 的时候,我们不会思考网络正在做什么,而且如今也不必思考。实际上,我认为很神奇的是,计算机接口已经如此先进,让大多数人上网的时候完全不思考网络是如何工作的。但是,网页抓取需要抛开一些接口的遮挡,不仅是在浏览器层(它如何解释所有的 HTML、CSS 和 JavaScript),有时也包括网络连接层。我们通过下面的例子让你对浏览器获取信息的过程有一个基本的认识。Alice 有一台网络服务器。Bob 有一台台式机正试图连接到 Alice 的服务器。当一台机器想与另一台机器对话时,下面的某个行为将会发生。(1) Bob 的电脑发送一串 1 和 0 比特值,表示电路上的高低电压。这些比特构成了一种信息,包括请求头和消息体。请求头包含当前 Bob 的本地路由器 MAC 地址和 Alice 的 IP 地址。消息体包含 Bob 对 Alice 服务器应用的请求。(2) Bob 的本地路由器收到所有 1 和 0 比特值,把它们理解成一个数据包(packet),从 Bob 自己的 MAC 地址“寄到”Alice 的 IP 地址。他的路由器把数据包“盖上”自己的 IP 地址作为“发件”地址,然后通过互联网发出去。(3) Bob 的数据包游历了一些中介服务器,沿着正确的物理 / 电路路径前进,到了 Alice 的服务器。(4) Alice 的服务器在她的 IP 地址收到了数据包。(5) Alice 的服务器读取数据包请求头里的目标端口,然后把它传递到对应的应用——网络服务器应用。(目标端口通常是网络应用的 80 端口,可以理解成数据包的“房间号”,IP 地址就是“街道地址”)。(6) 网络服务器应用从服务器处理器收到一串数据,数据是这样的:● 这是一个 GET 请求● 请求文件 index.html(7) 网络服务器应用找到对应的 HTML 文件,把它打包成一个新的数据包发送给 Bob,然后通过它的本地路由器发出去,用同样的过程回传到 Bob 的机器上。瞧!我们就这样实现了互联网。那么,在这场数据交换中,Web 浏览器是从哪里开始参与的?完全没有参与。其实,在互联网的历史中,浏览器是一个比较新的发明,始于 1990 年的 Nexus 浏览器。的确,Web 浏览器是一个非常有用的应用,它创建信息的数据包,命令操作系统发送它们,然后把你获取的数据解释成漂亮的图像、声音、视频和文字。但是,Web 浏览器就是代码,而代码可以分解成许多基本组件,可重写、重用,以及做成我们想要的任何东西。Web 浏览器可以让处理器将数据发送到那些对接无线(或有线)网络接口的应用上,但是你可以用短短的 3 行 Python 代码实现这些功能:from urllib.request import urlopenhtml = urlopen('http://pythonscraping.com/pages/page1.html')print(html.read())你可以使用 GitHub 仓库中的 iPython notebook for Chapter 1(https://github.com/REMitchell/python-scraping/blob/master/Chapter01_BeginningToScrape.ipynb)运行以上代码,也可以把上面这段代码保存为 scrapetest.py,然后在终端运行如下命令:$ python scrapetest.py注意,如果你的设备上也安装了 Python 2.x,并且同时运行两个版本的 Python,可能需要直接指明版本才能运行 Python 3.x 代码:$ python3 scrapetest.py这将会输出 http://pythonscraping.com/pages/page1.html 这个网页的全部 HTML 代码。更准确地说,这会输出在域名为 http://pythonscraping.com 的服务器上 < 网络应用根地址 >/ pages 文件夹里的 HTML 文件 page1.html 的源代码。为什么将这些地址理解为“文件”而不是“页面”非常关键呢?现在大多数网页需要加载许多相关的资源文件,可能是图像文件、JavaScript 文件、CSS 文件,或你需要连接的其他各种网页内容。当 Web 浏览器遇到一个标签时,比如 ,会向服务器发起另一个请求,以获取 cuteKitten.jpg 文件中的数据为用户充分渲染网页。当然,你的 Python 程序没有返回并向服务器请求多个文件的逻辑,它只能读取你直接请求的单个 HTML 文件。from urllib.request import urlopen上面的代码其实已经表明了它的含义:它查找 Python 的 request 模块(在 urllib 库里面),只导入 urlopen 函数。urllib 是 Python 的标准库(就是说你不用额外安装就可以运行这个例子),包含了从网页请求数据,处理 cookie,甚至改变像请求头和用户代理这些元数据的函数。我们将在本书中广泛使用 urllib,所以建议你读读这个库的 Python 文档。urlopen 用来打开并读取一个从网络获取的远程对象。因为它是一个非常通用的函数(可以轻松读取 HTML 文件、图像文件或其他任何文件流),所以我们将在本书中频繁地使用它。1.2 BeautifulSoup简介“美味的汤,绿色的浓汤,在热气腾腾的盖碗里装!谁不愿意尝一尝,这样的好汤?晚餐用的汤,美味的汤!”BeautifulSoup 库的名字取自刘易斯 • 卡罗尔在《爱丽丝梦游仙境》里1的同名诗歌。在故事中,这首诗是素甲鱼 唱的。1Mock Turtle,它本身是一个双关语,指英国维多利亚时代的流行菜肴素甲鱼汤,它其实不是用甲鱼而是用牛肉做的,如同中国的豆制品素鸡,名为素鸡,其实与鸡无关。——译者注就像它在仙境中的说法一样,BeautifulSoup 尝试化平淡为神奇。它通过定位 HTML 标签来格式化和组织复杂的网页信息,用简单易用的 Python 对象为我们展现 XML 结构信息。1.2.1 安装BeautifulSoup由于 BeautifulSoup 库不是 Python 标准库,因此需要单独安装。如果你安装过 Python 库,可以使用你最喜爱的安装器并略过本小节,直接阅读 1.2.2 节。对于还没有安装过 Python 库的新手(或者需要温习的读者)来说,以下介绍的方法将会用于安装本书中的多个库,所以在后面你可能需要回顾本小节。在本书中,我们将使用 BeautifulSoup 4(也叫 BS4)。Crummy.com 中有 BeautifulSoup 4 的完整安装说明。Linux 系统上的基本安装方法是:$ sudo apt-get install python-bs4对于 macOS 系统,首先用以下命令安装 Python 的包管理器 pip:$ sudo easy_install pip然后运行以下命令来安装库。$ pip install beautifulsoup4另外,注意如果你的设备上同时安装了 Python 2.x 和 Python 3.x,你需要用 python3 运行 Python 3.x:$ python3 myScript.py安装包的时候,也要使用这条命令,否则包有可能安装到 Python 2.x 而不是 Python 3.x 里:$ sudo python3 setup.py install如果用 pip 安装,你还可以用 pip3 安装 Python 3.x 版本的包:$ pip3 install beautifulsoup4在 Windows 系统上安装包与在 Linux 和 macOS 上安装差不多。从下载页面下载最新的 BeautifulSoup 4 源代码,解压后进入文件,然后执行:> python setup.py install这样就可以了!BeautifulSoup 将被当作设备上的一个 Python 库。你可以在 Python 终端里导入它测试一下:$ python> from bs4 import BeautifulSoup如果没有错误,说明导入成功了。另外,还有一个 Windows 版 pip 的 .exe 格式安装器,装了之后你就可以轻松安装和管理包了:> pip install beautifulsoup4用虚拟环境保存库文件如果你同时负责多个 Python 项目,或者想要轻松打包某个项目及其关联的库文件,再或者你担心已安装的库之间可能有冲突,那么你可以安装一个 Python 虚拟环境来分而治之。当不用虚拟环境安装一个 Python 库的时候,你实际上是全局安装它。这通常需要有管理员权限,或者以 root 身份安装,这个库文件对设备上的每个用户和每个项目来说都是存在的。好在创建虚拟环境非常简单:$ virtualenv scrapingEnv这样就创建了一个叫作 scrapingEnv 的新环境,你需要先激活它再使用:$ cd scrapingEnv/$ source bin/activate激活环境之后,你会在命令行提示符前面看到环境名称,提醒你当前处于虚拟环境中。后面你安装的任何库和执行的任何程序都在这个环境下运行。在新建的 scrapingEnv 环境里,可以安装并使用 BeautifulSoup:(scrapingEnv)ryan$ pip install beautifulsoup4(scrapingEnv)ryan$ python> from bs4 import BeautifulSoup>当不再使用虚拟环境中的库时,可以通过 deactivate 命令来退出环境:(scrapingEnv)ryan$ deactivateryan$ python> from bs4 import BeautifulSoupTraceback (most recent call last): File "", line 1, in ImportError: No module named 'bs4'将项目关联的所有库单独放在一个虚拟环境里,还有助于轻松打包整个环境发送给其他人。只要他们机器上安装的 Python 版本和你的相同,你打包的代码就可以直接通过虚拟环境运行,不需要再安装任何库。尽管本书的例子都不要求你使用虚拟环境,但是请记住,你可以在任何时候激活并使用它。1.2.2 运行BeautifulSoupBeautifulSoup 库最常用的对象恰好就是 BeautifulSoup 对象。让我们把本章开头的例子调整一下再运行看看:from urllib.request import urlopenfrom bs4 import BeautifulSouphtml = urlopen('http://www.pythonscraping.com/pages/page1.html')bs = BeautifulSoup(html.read(), 'html.parser')print(bs.h1)输出结果是:

An Interesting Title

这里仅仅返回了页面上的第一个 h1 标签实例。通常情况下,一个页面也只有一个 h1 标签,但是在 Web 中这个惯例经常被打破,因此你应该意识到这里仅仅检索了该标签的第一个实例,而不一定是你寻找的那个。和前面网页抓取的例子一样,你导入 urlopen 函数,然后调用 html.read() 获取网页的 HTML 内容。除了文本字符串,BeautifulSoup 还可以使用 urlopen 直接返回的文件对象,而不需要先调用 .read() 函数:bs = BeautifulSoup(html, 'html.parser')这样就可以把 HTML 内容传到 BeautifulSoup 对象,转换成下面的结构:● html → ......● head → A Useful Page■ title → A Useful Page● body →

An Int...

Lorem ip...
■ h1 →

An Interesting Title

■ div →
Lorem Ipsum dolor...
可以看出,我们从网页中提取的

标签被嵌在 BeautifulSoup 对象结构的第二层(html → body → h1)。但是,当我们从对象里提取 h1 标签的时候,可以直接调用它:bs.h1其实,下面的所有函数调用都可以产生相同的结果:bs.html.body.h1bs.body.h1bs.html.h1当你创建一个 BeautifulSoup 对象时,需要传入两个参数:bs = BeautifulSoup(html.read(), 'html.parser')第一个参数是该对象所基于的 HTML 文本,第二个参数指定了你希望 BeautifulSoup 用来创建该对象的解析器。在大多数情况下,你选择任何一个解析器都差别不大。html.parser 是 Python 3 中的一个解析器,不需要单独安装。如果不是特殊场景的需要,本书中都将使用这个解析器。另一个常用的解析器是 lxml,可以通过 pip 命令安装:$ pip3 install lxmlBeautifulSoup 使用 lxml 解析器时,只需要改变解析器参数:bs = BeautifulSoup(html.read(), 'lxml')和 html.parser 相比,lxml 的优点在于解析“杂乱”或者包含错误语法的 HTML 代码的性能更优一些。它可以容忍并修正一些问题,例如未闭合的标签、未正确嵌套的标签,以及缺失的头(head)标签或正文(body)标签。lxml 也比 html.parser 更快,但是考虑到网络本身的速度将总是你最大的瓶颈,在网页抓取中速度并不是一个必备的优势。lxml 的一个缺点是它必须单独安装,并且它依赖于第三方的 C 语言库。相对于 html.parser 来说,这可能会导致可移植性和易用性问题。另外一个常用的 HTML 解析器是 html5lib。和 lxml 一样,html5lib 也是一个具有容错性的解析器,它甚至可以容忍语法更糟糕的 HTML。它也依赖于外部依赖,并且比 lxml 和 html.parser 都慢。尽管如此,如果你处理的是一些杂乱的或者手写的 HTML 网站,那么该解析器可能是一个不错的选择。可以通过安装并将 html5lib 字符串传递给 BeautifulSoup 对象来使用它:bs = BeautifulSoup(html.read(), 'html5lib')希望这个例子可以向你展示 BeautifulSoup 库的强大与简单。其实,任何 HTML(或 XML)文件的任意节点信息都可以被提取出来,只要目标信息的旁边或附近有标签就行。第 2 章将进一步探讨一些更复杂的 BeautifulSoup 函数,还会介绍正则表达式,以及如何把正则表达式用于 BeautifulSoup 以提取网站信息。1.2.3 可靠的网络连接以及异常的处理Web 是十分复杂的。网页数据格式不友好、网站服务器死机、目标数据的标签找不到,都是很麻烦的事情。网页抓取最痛苦的遭遇之一,就是爬虫运行的时候你洗洗睡了,梦想着明天一早数据就都会抓取好放在数据库里,结果第二天醒来,你看到的却是一个因某种数据格式异常导致运行错误的爬虫,在前一天当你不再盯着屏幕去睡觉之后,没过一会儿爬虫就不再运行了。那个时候,你可能想骂发明网站(以及那些奇葩的网络数据格式)的人,但是你真正应该斥责的人是你自己,为什么一开始不估计可能会出现的异常!让我们看看爬虫 import 语句后面的第一行代码,看看如何处理可能出现的异常:html = urlopen('http://www.pythonscraping.com/pages/page1.html')这行代码主要会发生两种异常:● 网页在服务器上不存在(或者获取页面的时候出现错误)● 服务器不存在发生第一种异常时,程序会返回 HTTP 错误。HTTP 错误可能是“404 Page Not Found”“500 Internal Server Error”等。对于所有类似情形,urlopen 函数都会抛出 HTTPError 异常。我们可以用下面的方式处理这种异常:from urllib.request import urlopenfrom urllib.error import HTTPErrortry: html = urlopen('http://www.pythonscraping.com/pages/page1.html')except HTTPError as e: print(e) # 返回空值,中断程序,或者执行另一个方案else: # 程序继续。注意:如果你已经在上面异常捕捉那一段代码里返回或中断(break), # 那么就不需要使用else语句了,这段代码也不会执行如果程序返回 HTTP 错误代码,程序就会显示错误内容,不再执行 else 语句后面的代码。如果服务器不存在(就是说链接 http://www.pythonscraping.com 打不开,或者是 URL 链接写错了),urlopen 会抛出一个 URLError 异常。这就意味着获取不到服务器,并且由于远程服务器负责返回 HTTP 状态代码,所以不能抛出 HTTPError 异常,而且还应该捕获到更严重的 URLError 异常。你可以增加以下检查代码:from urllib.request import urlopenfrom urllib.error import HTTPErrorfrom urllib.error import URLErrortry: html = urlopen('https://pythonscrapingthisurldoesnotexist.com')except HTTPError as e: print(e)except URLError as e: print('The server could not be found!')else: print('It Worked!')当然,即使从服务器成功获取网页,如果网页上的内容并非完全是我们期望的那样,仍然可能会出现异常。每当你调用 BeautifulSoup 对象里的一个标签时,增加一个检查条件以保证标签确实存在是很聪明的做法。如果你想要调用的标签不存在,BeautifulSoup 就会返回 None 对象。不过,如果再调用这个 None 对象下面的子标签,就会发生 AttributeError 错误。下面这行代码(nonExistentTag 是虚拟的标签,BeautifulSoup 对象里实际没有)print(bs.nonExistentTag)会返回一个 None 对象。处理和检查这个对象是十分必要的。如果你不检查,直接调用这个 None 对象的子标签,就会有麻烦,如下所示。print(bs.nonExistentTag.someTag)这时就会返回一个异常:AttributeError: 'NoneType' object has no attribute 'someTag'那么怎么才能避免这两种情形的异常呢?最简单的方式就是对两种情形进行检查:try: badContent = bs.nonExistingTag.anotherTagexcept AttributeError as e: print('Tag was not found')else: if badContent == None: print ('Tag was not found') else: print(badContent)初看这些检查与错误处理的代码会觉得有点儿累赘,但是我们可以重新简单组织一下代码,让它变得不那么难写(更重要的是,不那么难读)。例如,下面的代码是上面爬虫的另一种写法:from urllib.request import urlopenfrom urllib.error import HTTPErrorfrom bs4 import BeautifulSoupdef getTitle(url): try: html = urlopen(url) except HTTPError as e: return None try: bs = BeautifulSoup(html.read(), 'html.parser') title = bs.body.h1 except AttributeError as e: return None return titletitle = getTitle('http://www.pythonscraping.com/pages/page1.html')if title == None: print('Title could not be found')else: print(title)在这个例子中,我们创建了一个 getTitle 函数,它可以返回网页的标题,如果获取网页的时候遇到问题就返回一个 None 对象。在 getTitle 函数里面,我们像前面那样检查了 HTTPError,还检查了由于 URL 输入错误引起的 URLError,然后把两行 BeautifulSoup 代码封装在一个 try 语句里面。这两行中的任何一行有问题,都可能抛出 AttributeError(如果服务器不存在,html 就是一个 None 对象,html.read() 就会抛出 AttributeError)。其实,我们可以在 try 语句里面放任意多行代码,或者调用一个在任意位置都可以抛出 AttributeError 的函数。在写爬虫的时候,思考代码的总体格局,让代码既可以捕捉异常又容易阅读,这是很重要的。如果你还希望重用大量代码,那么拥有像 getSiteHTML 和 getTitle 这样的通用函数(具有周密的异常处理功能)会让快速、稳定地抓取网页变得简单易行。第 2 章 复杂 HTML 解析当米开朗基罗被问及如何完成《大卫》这样匠心独具的雕刻作品时,他有一段著名的回答:“很简单,你只要用锤子把石头上不像大卫的地方敲掉就行了。”虽然网页抓取和大理石雕刻大相径庭,但是当我们从复杂的网页中寻觅信息时,也必须持有类似的态度。有很多技巧可以帮我们“敲掉”网页上那些不需要的信息,直到找到目标信息。这一章将介绍如何解析复杂的 HTML 页面,从中提取出所需的信息。2.1 不是一直都要用锤子面对页面解析难题时,很容易不假思索地直接写几行语句来提取信息。但是,像这样鲁莽放纵地使用技术,只会让程序变得难以调试或脆弱不堪,甚至二者兼具。在开始解析网页之前,让我们看一些可以避免解析复杂 HTML 页面的方式。假如你已经确定了目标内容,可能是一个名字、一组统计数据或者一段文字。你的目标内容可能隐藏在一个 HTML“烂泥堆”的第 20 层标签里,带有许多没用的标签或 HTML 属性。假如你不经考虑地直接写出下面这样一行代码来提取内容:bs.find_all('table')[4].find_all('tr')[2].find('td').find_all('div')[1].find('a')

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载