Python中的Web爬虫

过去,收集数据是一项繁琐且成本高昂的工作。机器学习项目离不开数据。幸运的是,如今网络上有大量数据可供我们使用。我们可以从网上复制数据来创建我们的数据集。我们可以手动下载文件并将其保存到磁盘。但通过自动化数据采集,我们可以更有效地做到这一点。Python中有多种工具可以帮助实现自动化。

完成本教程后,你将学到:

  • 如何使用requests库通过HTTP读取在线数据
  • 如何使用pandas读取网页表格
  • 如何使用Selenium模拟浏览器操作

启动您的项目,阅读我的新书《Python for Machine Learning》,其中包含分步教程和所有示例的Python源代码文件。

让我们开始吧!

Python中的Web爬虫
照片由 Ray Bilcliff 拍摄。保留部分权利。

概述

本教程分为三个部分;它们是:

  • 使用requests库
  • 使用pandas在网上读取表格
  • 使用Selenium读取动态内容

使用Requests库

当我们谈论编写Python程序从网络读取数据时,不可避免地会涉及到 requests 库。您需要安装它(以及稍后将介绍的BeautifulSoup和lxml)。

它为您提供了一个可以轻松与网络交互的接口。

最简单的用例是从URL读取网页。

如果您熟悉HTTP,您可能还记得状态码200表示请求已成功满足。然后我们可以读取响应。在上面,我们读取了文本响应并获取了网页的HTML。如果数据是CSV或其他文本数据,我们可以在响应对象的text属性中获取。例如,这是我们如何从美联储经济数据中读取CSV

如果数据是JSON格式,我们可以将其读取为文本,或者让requests为您解码。例如,以下是将一些数据从GitHub中提取为JSON格式并将其转换为Python字典的方法:

但是,如果URL提供的是二进制数据,例如ZIP文件或JPEG图像,您需要获取content属性,因为这将是二进制数据。例如,这是我们如何下载一张图片(维基百科的标志):

既然我们已经获取了网页,我们应该如何提取数据呢?这已经超出了requests库的功能,但我们可以使用另一个库来帮忙。有两种方法,取决于我们想要如何指定数据。

第一种方法是将HTML视为一种XML文档,并使用XPath语言提取元素。在这种情况下,我们可以利用lxml库来首先创建一个文档对象模型(DOM),然后通过XPath进行搜索。

XPath是指定如何查找元素的字符串。lxml对象提供了一个xpath()函数来在DOM中搜索匹配XPath字符串的元素,可能会有多个匹配。上面的XPath表示在任何地方查找一个HTML元素,其<span>标签具有data-testid属性且值为“TemperatureValue”,并且class属性以“CurrentConditions”开头。我们可以从浏览器的开发者工具(例如,下面的Chrome截图)中通过检查HTML源代码来学习这一点。

这个例子是为了查找纽约市的温度,该温度由该网页的特定元素提供。我们知道XPath匹配的第一个元素是我们需要的,我们可以读取<span>标签内的文本。

另一种方法是使用CSS选择器在HTML文档上进行操作,我们可以利用BeautifulSoup库。

在上面,我们首先将HTML文本传递给BeautifulSoup。BeautifulSoup支持各种HTML解析器,它们各有不同的功能。在上面,我们使用了BeautifulSoup推荐的lxml库作为解析器(它通常也是最快的)。CSS选择器是一种不同的迷你语言,与XPath相比各有利弊。上面的选择器与我们在上一个示例中使用的XPath相同。因此,我们可以从第一个匹配的元素中获取相同的温度。

以下是根据网络实时信息打印纽约当前温度的完整代码:

您可以想象,通过定期运行此脚本,您可以收集温度的时间序列数据。同样,我们可以从各种网站自动收集数据。这就是我们如何为机器学习项目获取数据。

使用Pandas读取网页表格

很多时候,网页会使用表格来承载数据。如果页面足够简单,我们甚至可以跳过检查它来找出XPath或CSS选择器,并使用pandas一次性获取页面上的所有表格。这很容易做到,只需一行代码即可完成。

Pandas中的read_html()函数读取URL并查找页面上的所有表格。每个表格都会被转换为一个pandas DataFrame,然后将它们全部返回在一个列表中。在此示例中,我们正在读取美联储的各种利率,碰巧这个页面只有一个表格。表格列由pandas自动识别。

很有可能并非所有表格都是我们感兴趣的。有时,网页会仅使用表格来格式化页面,但pandas可能不够智能,无法分辨。因此,我们需要测试并筛选read_html()函数返回的结果。

想开始学习机器学习 Python 吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

使用Selenium读取动态内容

现代网页的很大一部分都充满了JavaScript。这提供了更fancy的体验,但却成为了程序提取数据的障碍。一个例子是雅虎的主页,如果我们只是加载页面并查找所有新闻标题,其数量会远少于我们在浏览器中看到的数量。

这是因为像这样的网页依赖于JavaScript来填充内容。像AngularJS或React这样著名的Web框架支持这一类。Python库,如requests,不理解JavaScript。因此,您看到的结果会不同。如果您要获取的网页数据是其中之一,您可以研究JavaScript是如何被调用的,并在您的程序中模仿浏览器的行为。但这可能太繁琐,难以实现。

另一种方法是让真实的浏览器读取网页,而不是使用requests。这就是Selenium可以做到的。在使用它之前,我们需要安装库:

但Selenium只是一个控制浏览器的框架。您需要在计算机上安装浏览器以及连接Selenium到浏览器的驱动程序。如果您打算使用Chrome,您还需要下载并安装ChromeDriver。您需要将驱动程序放在可执行路径中,以便Selenium可以像普通命令一样调用它。例如,在Linux中,您只需要从下载的ZIP文件中获取chromedriver可执行文件,并将其放在/usr/local/bin中。

同样,如果您使用的是Firefox,您需要GeckoDriver。有关设置Selenium的更多详细信息,您应该参考其文档

之后,您可以使用Python脚本来控制浏览器行为。例如:

上面的代码工作原理如下。我们首先以无头模式启动浏览器,这意味着我们要求Chrome启动但不显示在屏幕上。如果我们要远程运行脚本,这一点很重要,因为可能没有GUI支持。请注意,每个浏览器开发方式不同,因此我们使用的选项语法特定于Chrome。如果我们使用Firefox,代码将是这样的:

启动浏览器后,我们让它加载一个URL。但由于网络传输页面需要时间,并且浏览器需要时间来渲染它,所以在进行下一步操作之前,我们应该等待浏览器准备就绪。我们使用JavaScript来检测浏览器是否已完成渲染。我们让Selenium为我们运行一段JavaScript代码,并通过execute_script()函数告诉我们结果。我们利用Selenium的WebDriverWait工具来运行它,直到成功或直到30秒超时。页面加载后,我们滚动到页面底部,以便触发JavaScript加载更多内容。然后,我们无条件等待一秒钟,以确保浏览器触发了JavaScript,然后再次等待页面准备就绪。之后,我们可以使用XPath(或选择器)提取新闻标题元素。由于浏览器是一个外部程序,我们负责在脚本中关闭它。

Selenium的使用在多个方面与requests库不同。首先,您的Python代码中从不直接包含网页内容。相反,您在需要时引用浏览器的内容。因此,find_elements()函数返回的Web元素是指外部浏览器中的对象,所以我们必须在完成使用它们之前不要关闭浏览器。其次,所有操作都应基于浏览器交互,而不是网络请求。因此,您需要通过模拟键盘和鼠标移动来控制浏览器。但作为回报,您拥有了支持JavaScript的完整功能浏览器。例如,您可以使用JavaScript来检查页面上元素的大小和位置,这些信息只有在HTML元素渲染后才能知道。

Selenium框架提供了许多我们可以涵盖的功能。它很强大,但由于它连接到浏览器,使用起来比requests库要求更高,而且速度也慢得多。通常,这是从网络上采集信息的最后手段。

进一步阅读

Python中另一个著名的网络爬虫库是我们上面没有介绍的Scrapy。它就像将requests库与BeautifulSoup结合在一起。Web协议很复杂。有时我们需要管理Web Cookie或使用POST方法向请求提供额外数据。所有这些都可以使用requests库通过不同的函数或附加参数来完成。以下是一些供您深入研究的资源:

文章

API文档

书籍

总结

在本教程中,您了解了可用于从网络获取内容的工具。

具体来说,你学到了:

  • 如何使用requests库发送HTTP请求并从其响应中提取数据
  • 如何构建HTML的文档对象模型,以便我们可以找到网页上的某些特定信息
  • 如何使用pandas快速轻松地读取网页上的表格
  • 如何使用Selenium控制浏览器来处理网页上的动态内容

掌握机器学习 Python!

Python For Machine Learning

更自信地用 Python 编写代码

...从学习实用的 Python 技巧开始

在我的新电子书中探索如何实现
用于机器学习的 Python

它提供自学教程数百个可运行的代码,为您提供包括以下技能:
调试性能分析鸭子类型装饰器部署等等...

向您展示高级 Python 工具箱,用于
您的项目


查看内容

Python中的网络爬虫的14条回复

  1. YF 2022年4月22日晚上12:52 #

    这里有一个拼写错误。

    df = ppd.read_csv(csvbuffer)

    “ppd”应该是“pd”

    • James Carmichael 2022年4月24日凌晨3:36 #

      感谢您的反馈 YF!

  2. Selda 2022年4月22日晚上5:13 #

    感谢您提供如此详细且有用的页面。有一件事,这不算是网络抓取吗?据我所知,网络爬虫是查找或发现网络上的URL或链接。

    • James Carmichael 2022年4月24日凌晨3:35 #

      嗨 Selda…是的,这种技术通常被称为网络抓取。

  3. Luis Gonzalez 2022年4月23日凌晨12:04 #

    错误
    df = ppd.read_csv(csvbuffer)

    正确

    df = pd.read_csv(csvbuffer)

    • James Carmichael 2022年4月24日凌晨3:32 #

      嗨 Luis…感谢您的反馈!

  4. suchi banerjee 2022年4月26日晚上2:21 #

    很棒且全面的文章。它有助于理解不同的方法。然而,由于没有标准的网站开发模板,要拥有一个通用的工具来从网页收集数据确实很困难。您对此有什么想法吗?

  5. Rina 2022年5月29日早上7:52 #

    感谢您的全面步骤。请问如何抓取推特数据?这里有人能提供链接吗?

  6. Billie 2022年6月10日下午2:53 #

    感谢本教程。我怎样才能知道如何抓取私人GitHub仓库的数据?

    • James Carmichael 2022年6月11日早上9:04 #

      感谢您的反馈 Billie!我不知道有任何方法可以执行该任务。

  7. Abdul Hannan 2022年12月26日凌晨12:46 #

    您好,希望您一切安好。
    请问我怎样才能从任何网站上抓取任何数据?

留下回复

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。