在过去,收集数据是一项繁琐的工作,有时非常昂贵。机器学习项目不能没有数据。幸运的是,我们现在在网络上有很多数据可供我们使用。我们可以从 Web 复制数据来创建数据集。我们可以手动下载文件并将其保存到磁盘。但是,我们可以通过自动化数据收集来更有效地做到这一点。Python中有几种工具可以帮助自动化。
完成本教程后,您将学习:
- 如何使用 库通过 HTTP 读取网络数据
- 如何使用 读取网页上的表格
- 如何使用 模拟浏览器操作
本教程分为三个部分;它们是:
- 使用 库
- 使用 在网络上阅读表格
- 用 阅读动态内容
当我们谈论编写Python程序从Web上读取时,不可避免的是我们无法避免库。您需要安装它(以及我们稍后将介绍的BeautifulSoup和lxml):
它为您提供了一个界面,可让您轻松与网络进行交互。
非常简单的用例是从URL读取网页:
运行结果:
如果您熟悉 HTTP,您可能还记得状态代码 200 表示请求已成功完成。然后我们可以阅读响应。在上面,我们阅读文本响应并获取网页的HTML。如果它是CSV或其他一些文本数据,我们可以在响应对象的属性中获取它们。例如,这就是我们从美联储经济学数据中读取CSV的方法:
以下例子会用到pandas 模块 :
安装:
运行结果:
如果数据是JSON的形式,我们可以将其读取为文本,甚至可以为您解码。例如,以下是以JSON格式从GitHub中提取一些数据并将其转换为Python字典:
运行结果:
但是,如果 URL 为您提供了一些二进制数据,例如 ZIP 文件或 JPEG 图像,则需要在属性中获取它们,因为这将是二进制数据。例如,这就是我们下载图像(维基百科的标志)的方式:
运行结果:
鉴于我们已经获得了网页,我们应该如何提取数据?这超出了所能提供给我们的范围,但我们可以使用不同的library 来提供帮助。有两种方法可以做到这一点,这取决于我们想要如何指定数据。
第一种方法是将 HTML 视为一种 XML 文档,并使用 XPath 语言提取元素。在这种情况下,我们可以利用该库首先创建一个文档对象模型(DOM),然后通过XPath进行搜索:
XPath 是一个字符串,它指定如何查找元素。lxml 对象提供了一个函数,用于在 DOM 中搜索与 XPath 字符串匹配的元素,这些元素可以是多个匹配项。上面的 XPath 意味着在具有标记和属性与 “” 匹配且以 “” 开头的任何位置查找 HTML 元素。我们可以通过检查HTML源代码从浏览器的开发人员工具(例如,下面的Chrome屏幕截图)中学习这一点。
这个例子是找到纽约市的温度,由我们从这个网页获得的这个特定元素提供。我们知道与 XPath 匹配的第一个元素是我们需要的,我们可以读取标记内的文本。
另一种方法是在HTML文档上使用CSS选择器,我们可以利用BeautifulSoup库:
运行结果:
在上面,我们首先将HTML文本传递给BeautifulSoup。BeautifulSoup支持各种HTML解析器,每个解析器具有不同的功能。在上面,我们使用库作为BeautifulSoup推荐的解析器(它通常也是最快的)。CSS选择器是一种不同的迷你语言,与XPath相比有优点和缺点。上面的选择器与我们在上一个示例中使用的 XPath 相同。因此,我们可以从第一个匹配的元素中获得相同的温度。
以下是根据网络上的实时信息打印纽约当前温度的完整代码:
可以想象,您可以通过定期运行此脚本来收集温度的时间序列。同样,我们可以从各种网站自动收集数据。这就是我们为机器学习项目获取数据的方法。
通常,网页将使用表格来承载数据。如果页面足够简单,我们甚至可以跳过检查它以找出XPath或CSS选择器,并使用pandas一次性获取页面上的所有表格。它很简单,可以在一行中完成:
pandas 中的函数读取 URL 并查找页面上的所有表。每个表都转换为 pandas DataFrame,然后在列表中返回所有表。在这个例子中,我们正在阅读美联储的各种利率,而美联储恰好在这个页面上只有一个表格。表列由 pandas 自动标识。
很可能并非所有表格都是我们感兴趣的。有时,网页会使用表格作为格式化页面的一种方式,但熊猫可能不够聪明, 无法分辨。因此,我们需要测试并挑选函数返回的结果。
现代网页的很大一部分充满了JavaScript。这给了我们一个更奇特的体验,但成为一个障碍,用作提取数据的程序。一个例子是雅虎的主页,如果我们只加载页面并找到所有新闻标题,那么在浏览器上看到的要少得多:
运行结果:
这是因为像这样的网页依靠JavaScript来填充内容。著名的Web框架,如AngularJS或React,是这一类别的幕后推手。Python 库,比如 ,不理解 JavaScript。因此,您将看到不同的结果。如果你想从网上获取的数据就是其中之一,你可以研究JavaScript是如何被调用的,并在你的程序中模仿浏览器的行为。但这可能太乏味了,无法使其正常工作。
另一种方法是要求真正的浏览器读取网页,而不是使用。这就是可以做的。在使用它之前,我们需要安装库:
但Selenium只是一个控制浏览器的框架。您需要在计算机上安装浏览器以及将Selenium连接到浏览器的驱动程序。如果您打算使用Chrome,则还需要下载并安装ChromeDriver。您需要将驱动程序放在可执行路径中,以便Selenium可以像普通命令一样调用它。
同样,如果你使用的是Firefox,你需要GeckoDriver。有关设置Selenium的更多详细信息,请参阅其文档。
之后,您可以使用 Python 脚本来控制浏览器行为。例如:
上述代码的工作原理如下。我们首先以无外设模式启动浏览器,这意味着我们要求Chrome启动但不显示在屏幕上。如果我们想远程运行脚本,这很重要,因为可能没有任何GUI支持。请注意,每个浏览器的开发方式都不同,因此我们使用的选项语法特定于Chrome。如果我们使用Firefox,代码将是这样的:
启动浏览器后,我们会为其提供一个要加载的 URL。但是,由于网络需要时间来交付页面,并且浏览器需要时间来呈现它,因此我们应该等到浏览器准备就绪后再继续下一个操作。我们检测浏览器是否已经使用 JavaScript 完成了渲染。我们让Selenium为我们运行JavaScript代码,并使用该函数告诉我们结果。我们利用Selenium的工具运行它,直到它成功或直到30秒超时。加载页面时,我们滚动到页面底部,以便可以触发JavaScript以加载更多内容。然后,我们无条件地等待一秒钟,以确保浏览器触发了JavaScript,然后等待页面再次准备就绪。之后,我们可以使用XPath(或者使用CSS选择器)提取新闻标题元素。由于浏览器是外部程序,因此我们负责在脚本中关闭它。
使用硒在几个方面与使用库不同。首先,您永远不会直接在Python代码中拥有Web内容。相反,您可以在需要时引用浏览器的内容。因此,该函数返回的Web元素引用外部浏览器内部的对象,因此在完成使用它们之前,我们不得关闭浏览器。其次,所有操作都应基于浏览器交互而不是网络请求。因此,您需要通过模拟键盘和鼠标移动来控制浏览器。但作为回报,您拥有支持JavaScript的全功能浏览器。例如,您可以使用 JavaScript 检查页面上某个元素的大小和位置,只有在呈现 HTML 元素后,您才会知道这些大小和位置。
Selenium框架提供了更多功能,我们可以在这里介绍。它功能强大,但是由于它连接到浏览器,因此使用它比库的要求更高,并且速度要慢得多。通常,这是从网络收集信息的最后手段。