首页 >> 大全

3种抓取其中数据的方法,你都知道吗?

2022-06-04 大全 300 作者:考证青年

网络爬虫:3种网页抓取方法

3种方法来抓取其中的数据。首先是正则表达式,然后是流行的模块,最后是强大的 lxml 模块。

1 正则表达式

如果您是正则表达式的新手,或者需要一些提示,您可以查看它以获得完整的介绍。即使你在其他编程语言中使用过正则表达式,我仍然建议你逐步复习中文正则表达式的编写。

由于可以在每章中构建或使用前几章的内容,因此我建议您遵循类似于本书代码库的文件结构。所有代码都可以从代码库的代码目录运行,以便导入工作正常。如果您希望创建不同的结构,请注意所有来自其他章节的导入都需要更改(例如,来自下面代码中的 chp1.r)。

当我们使用正则表达式获取国家(或地区)地区数据时,首先需要尝试匹配``元素中的内容,如下图所示。

>>> import re>>> from chp1.advanced_link_crawler import download>>> url = 'http://example.python-scraping.com/view/UnitedKingdom-239'>>> html = download(url)>>> re.findall(r'(.*?)', html)['', '244,820 square kilometres', '62,348,447', 'GB', 'United Kingdom', 'London', 'EU', '.uk', 'GBP', 'Pound', '44', '@# #@@|@## #@@|@@# #@@|@@## #@@|@#@ #@@|@@#@ #@@|GIR0AA', '^(([A-Z]d{2}[A-Z]{2})|([A-Z]d{3}[A-Z]{2})|([A-Z]{2}d{2} [A-Z]{2})|([A-Z]{2}d{3}[A-Z]{2})|([A-Z]d[A-Z]d[A-Z]{2}) |([A-Z]{2}d[A-Z]d[A-Z]{2})|(GIR0AA))$', 'en-GB,cy-GB,gd', '
IE
']

从以上结果可以看出,``标签用于多个国家(或地区)属性。如果我们只想抓取国家(或地区)区域,我们可以选择第二个匹配元素,如下图。

>>> re.findall('(.*?)', html)[1]'244,820 square kilometres'

虽然这个方案现在可用,但如果页面发生变化,它很可能会失败。例如,表已更改为删除第二个匹配元素中的区域数据。如果我们只抓取当前的数据,我们可以忽略这种未来可能发生的变化。但是,如果我们希望将来能够再次获取这些数据,我们需要提出一个更强大的解决方案,尽可能避免这种布局更改的影响。为了使正则表达式更明确,我们可以添加它的父元素 `,它应该是唯一的,因为它有一个 ID 属性。

>>> re.findall('(.*?)', html)['244,820 square kilometres']

这个迭代版本看起来好一点,但是网页更新还有很多其他的方式也会让这个正则表达式不令人满意。例如,将双引号更改为单引号,在`标签之间添加额外的空格,或更改`等。下面是一个尝试支持这些可能性的改进版本。

>>> re.findall('''.*?(.*?)''', html)['244,820 square kilometres']

虽然这个正则表达式更容易适应未来的变化,但它也存在构造困难、可读性差的问题。此外,还有许多其他小的布局更改使此正则表达式无法令人满意,例如向`标签添加标题属性,或修改其 CSS 类或 ID 的 tr、td` 元素。

从这个例子可以看出,正则表达式为我们提供了一种抓取数据的捷径,但是这种方法过于脆弱,在页面更新后容易出现问题。幸运的是,有更好的数据提取解决方案,例如我们将在本章中介绍的其他抓取库。

是一个非常流行的库,它解析网页并提供方便的界面来定位内容。如果您尚未安装该模块,您可以使用以下命令安装其最新版本。

pip install beautifulsoup4

使用 Soup 的第一步是将下载的 HTML 内容解析成一个汤文档。由于许多网页不是格式良好的 HTML,因此 Soup 需要更正其标签的打开和关闭状态。例如,在下面这个简单网页的清单中,存在属性值和未闭合标签周围缺少引号的问题。

  • Area
  • Population

如果列表项被解析为 Area 列表项的子项,而不是两个并排的列表项,我们将在获取时得到错误的结果。让我们看看 Soup 是如何处理它的。

>>> from bs4 import BeautifulSoup>>> from pprint import pprint>>> broken_html = '
  • Area
  • Population
'>>> # parse the HTML>>> soup = BeautifulSoup(broken_html, 'html.parser')>>> fixed_html = soup.prettify()>>> pprint(fixed_html)
  • Area
  • Population

我们可以看到使用默认的html。没有得到正确解析的 HTML。从前面的代码片段可以看出,由于它使用了嵌套的 li 元素,会导致定位困难。幸运的是,我们还有其他解析器可供选择。我们可以安装 LXML(详见 2.2.3 部分),或者使用 . 要安装,只需使用 pip。

pip install html5lib

现在,我们可以重复此代码,只需对解析器进行以下更改。

>>> soup = BeautifulSoup(broken_html, 'html5lib')>>> fixed_html = soup.prettify()>>> pprint(fixed_html) 
  • Area
  • Population

此时,使用的已经正确解析了缺少的属性引号和结束标记,并且还添加了和标记,使其成为一个完整的 HTML 文档。使用 lxml 时也可以看到类似的结果。

现在,我们可以使用 find() 和 () 方法来定位我们需要的元素。

>>> ul = soup.find('ul', attrs={'class':'country_or_district'})>>> ul.find('li') # returns just the first match
  • Area
  • >>> ul.find_all('li') # returns all matches[
  • Area
  • ,
  • Population
  • 有关可用方法和参数的完整列表,请访问 Soup 的官方文档。

    以下是使用此方法从示例网站中提取国家(或领土)区域数据的完整代码。

    >>> from bs4 import BeautifulSoup>>> url = 'http://example.python-scraping.com/places/view/United-Kingdom-239'>>> html = download(url)>>> soup = BeautifulSoup(html)>>> # locate the area row>>> tr = soup.find(attrs={'id':'places_area__row'})>>> td = tr.find(attrs={'class':'w2p_fw'}) # locate the data element>>> area = td.text # extract the text from the data element>>> print(area)244,820 square kilometres

    此代码虽然比正则表达式代码更复杂,但更易于构建和理解。此外,布局的小变化,如额外的空白和制表符属性,我们不必再担心了。我们还知道,即使页面包含不完整的 HTML,Soup 也可以帮助我们清理页面,从而使我们能够从非常不完整的网站代码中提取数据。

    3Lxml

    lxml

    它是基于此 XML 解析库构建的库。它是用 C 语言编写的,解析速度比 Soup 快,但安装过程也比较复杂,尤其是 . 最新的安装说明可供参考。如果您自己安装库有困难,您也可以使用它。

    您可能不熟悉它,但它是由公司员工创建的包和环境管理器,主要专注于开源数据科学包。您可以按照其安装说明下载并安装它。请务必注意,使用的快速安装会将您的设置设置为安装 Conda 的位置。

    与 Soup 一样,使用 lxml 模块的第一步是将可能无效的 HTML 解析为统一格式。下面是使用此模块解析相同的不完整 HTML 的示例。

    >>> from lxml.html import fromstring, tostring>>> broken_html = '
    • Area
    • Population
    '>>> tree = fromstring(broken_html) # parse the HTML>>> fixed_html = tostring(tree, pretty_print=True)>>> print(fixed_html)
    • Area
    • Population

    同样,lxml 正确解析属性周围缺少的引号并关闭标签,但模块不会添加和标签。这些都不是标准 XML 的要求,因此 lxml 没有必要插入它们。

    解析输入内容后,进入选择元素的步骤。此时,lxml 有几种不同的方法,例如类似于 Soup 的 XPath 选择器和 find() 方法。然而,对于这个例子,我们将使用 CSS 选择器,因为它们更简洁,可以在第 5 章解析动态内容时重用。一些读者可能已经熟悉选择器,因为他们使用选择器或在前端的使用网络应用程序开发。在本章后面,我们将比较这些选择器与 XPath 的性能。要使用 CSS 选择器,您可能需要先安装该库,如下所示。

    pip install cssselect

    现在,我们可以使用 lxml 的 CSS 选择器从示例页面中提取区域数据。

    >>> tree = fromstring(html)>>> td = tree.cssselect('tr#places_area__row > td.w2p_fw')[0]>>> area = td.text_content()>>> print(area)244,820 square kilometres

    通过使用代码树上的方法,我们可以使用 CSS 语法选择表中 ID 为行的元素,然后选择子表数据标签为 class 。由于返回的是一个列表,我们需要获取其中的第一个结果并调用一个方法,该方法遍历所有子元素并返回每个元素的关联文本。在这种情况下,虽然我们只有一个元素,但此功能对于更复杂的提取示例很有用。

    郑重声明:本文版权归原作者所有,转载文章仅出于传播更多信息之目的。如作者信息标注有误,请尽快联系我们修改或删除,谢谢。

    关于我们

    最火推荐

    小编推荐

    联系我们


    版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
    Powered By Z-BlogPHP.
    复制成功
    微信号:
    我知道了