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

1 正则表达式

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

>>> 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)['<img />', '244,820 square kilometres', '62,348,447', 'GB', 'United Kingdom', 'London', '<a>EU</a>', '.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', '<div><a>IE </a></div>']

从上述结果中可以看出,多个国家(或地区)属性都使用了``标签。如果我们只想抓取国家(或地区)面积,可以只选择第二个匹配的元素,如下所示。

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

虽然现在可以使用这个方案,但是如果网页发生变化,该方案很可能就会失效。比如表格发生了变化,去除了第二个匹配元素中的面积数据。如果我们只在当下抓取数据,就可以忽略这种未来可能发生的变化。但是,如果我们希望在未来某一时刻能够再次抓取该数据,就需要给出更加健壮的解决方案,从而尽可能避免这种布局变化所带来的影响。想要该正则表达式更加明确,我们可以将其父元素``也加入进来,由于该元素具有ID属性,所以应该是唯一的。

>>> re.findall('<label for="places_area">Area: </label>(.*?)', html)['244,820 square kilometres']

这个迭代版本看起来更好一些,但是网页更新还有很多其他方式,同样可以让该正则表达式无法满足。比如,将双引号变为单引号,`标签之间添加多余的空格,或是变更area_label`等。下面是尝试支持这些可能性的改进版本。

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

虽然该正则表达式更容易适应未来变化,但又存在难以构造、可读性差的问题。此外,还有很多其他微小的布局变化也会使该正则表达式无法满足,比如在`标签里添加title属性,或者tr、td`元素修改了它们的CSS类或ID。

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

2 Beautiful Soup

Beautiful Soup

是一个非常流行的Python库,它可以解析网页,并提供了定位内容的便捷接口。如果你还没有安装该模块,可以使用下面的命令安装其最新版本。

pip install beautifulsoup4

使用Beautiful Soup的第一步是将已下载的HTML内容解析为soup文档。由于许多网页都不具备良好的HTML格式,因此Beautiful Soup需要对其标签开合状态进行修正。例如,在下面这个简单网页的列表中,存在属性值两侧引号缺失和标签未闭合的问题。

<ul><li>Area </li><li>Population</li></ul>

如果Population列表项被解析为Area列表项的子元素,而不是并列的两个列表项的话,我们在抓取时就会得到错误的结果。下面让我们看一下Beautiful Soup是如何处理的。

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

我们可以看到,使用默认的html.parser并没有得到正确解析的HTML。从前面的代码片段可以看出,由于它使用了嵌套的li元素,因此可能会导致定位困难。幸运的是,我们还有其他解析器可以选择。我们可以安装LXML(2.2.3节中将会详细介绍),或使用html5lib。要想安装html5lib,只需使用pip。

pip install html5lib

现在,我们可以重复这段代码,只对解析器做如下变更。

>>> soup = BeautifulSoup(broken_html, 'html5lib')>>> fixed_html = soup.prettify()>>> pprint(fixed_html) <ul> <li> Area </li> <li> Population </li> </ul>

此时,使用了html5lib的BeautifulSoup已经能够正确解析缺失的属性引号以及闭合标签,并且还添加了和标签,使其成为完整的HTML文档。当你使用lxml时,也可以看到类似的结果。

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

>>> ul = soup.find('ul', attrs={'class':'country_or_district'})>>> ul.find('li') # returns just the first match<li>Area</li>>>> ul.find_all('li') # returns all matches[<li>Area</li>, <li>Population</li>

想要了解可用方法和参数的完整列表,请访问Beautiful 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,Beautiful Soup也能帮助我们整理该页面,从而让我们可以从非常不完整的网站代码中抽取数据。

3 Lxml

Lxml

是基于libxml2这一XML解析库构建的Python库,它使用C语言编写,解析速度比Beautiful Soup更快,不过安装过程也更为复杂,尤其是在Windows中。如果你在自行安装该库时遇到困难,也可以使用Anaconda来实现。

你可能对Anaconda不太熟悉,它是由Continuum Analytics公司员工创建的主要专注于开源数据科学包的包和环境管理器。你可以按照其安装说明下载及安装Anaconda。需要注意的是,使用Anaconda的快速安装会将你的PYTHON_PATH设置为Conda的Python安装位置。

和Beautiful Soup一样,使用lxml模块的第一步也是将有可能不合法的HTML解析为统一格式。下面是使用该模块解析同一个不完整HTML的例子。

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

同样地,lxml也可以正确解析属性两侧缺失的引号,并闭合标签,不过该模块没有额外添加和标签。这些都不是标准XML的要求,因此对于lxml来说,插入它们并不是必要的。

解析完输入内容之后,进入选择元素的步骤,此时lxml有几种不同的方法,比如XPath选择器和类似Beautiful Soup的find()方法。不过,在本例中,我们将会使用CSS选择器,因为它更加简洁,并且能够在第5章解析动态内容时得以复用。一些读者可能由于他们在jQuery选择器方面的经验或是前端Web应用开发中的使用对它们已经有所熟悉。在本章的后续部分,我们将对比这些选择器与XPath的性能。要想使用CSS选择器,你可能需要先安装cssselect库,如下所示。

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

通过对代码树使用cssselect方法,我们可以利用CSS语法来选择表格中ID为places_area__row的行元素,然后是类为w2p_fw的子表格数据标签。由于cssselect返回的是一个列表,我们需要获取其中的第一个结果,并调用text_content方法,以迭代所有子元素并返回每个元素的相关文本。

新手必看篇!3种简单的网络数据抓取相关推荐

  1. python的难点_初学python的操作难点总结(新手必看篇)

    如下所示: 1 在cmd下 盘与盘之间的切换 直接 D或d: 就好 2 查找当前盘或者文件下面的目录 直接 dir 3 想在一个盘下进去一个文件夹,用cd空格目标文件 cd p 4 写文件的第一个字母 ...

  2. python新手入门总结_初学python的操作难点总结(新手必看篇)

    如下所示: 1 在cmd下 盘与盘之间的切换 直接 D或d: 就好 2 查找当前盘或者文件下面的目录 直接 dir 3 想在一个盘下进去一个文件夹,用cd空格目标文件 cd p 4 写文件的第一个字母 ...

  3. 2020年最佳的5种社交媒体的数据抓取/网络爬虫工具

    2020年最佳的5种社交媒体的数据抓取/网络爬虫工具 查看原文章: 2020年最佳的5种社交媒体的网络爬虫工具 社交媒体数据抓取工具通常是指一种自动化网络爬虫工具,可从社交媒体渠道提取数据.它不仅包括 ...

  4. Web前端新手必看的7种技术,从菜鸟到高级开发的蜕变!

    随着互联网发展,Web前端开发逐渐走红.由于大学没有开设前端课程,知识体系不够规范完整,每个人对它的认识也各不相同,加之互联网技术更新迭代迅速今天给你解读一下,学习Web前端的基本需要掌握的知识. 具 ...

  5. python新手难点_汇总初学python时的28个操作难点(新手必看篇)

    前言: 今天带来的内容是针对刚学习Python的程序员,内容详细的介绍了Python操作难点总结,换句话说就是一些基础的小知识,为了更效率的运用Python,喜欢的话直接收藏留着慢慢看就行了. 内容一 ...

  6. 【Android开发--新手必看篇】网络管家(判断是否联网)

    Android笔记 ​ --网络管家 [若对该知识点有更多想了解的,欢迎私信博主~~] 网络管家 一:使用 制作判断网络状态的方法 public static boolean isNetworkCon ...

  7. 【Linux学习手册--新手必看篇】命令:chpasswd

    Linux笔记 ​ --Linux命令 [若对该知识点有更多想了解的,欢迎私信博主~~] chpasswd 说明 ​ 批量修改用户密码 语法 ​ echo 用户名:密码 | chpasswd ​ ch ...

  8. 新手必看!单片机掉电检测与数据掉电保存方案

    单片机在正常工作时,因某种原因造成突然掉电,将会丢失数据存储器(RAM)里的数据.在某些应用场合如测量.控制等领域,单片机正常工作中采集和运算出一些重要数据,待下次上电后需要恢复这些重要数据. 因此, ...

  9. R语言实现简单的网页数据抓取

    在知乎遇到这样一个问题. https://www.zhihu.com/question/26385408/answer/147009602 这是要爬取的内容的网页: R语言的代码的实现方式如下: #安 ...

最新文章

  1. 2021-2027年中国医疗美容市场研究及前瞻分析报告
  2. 压力测试工具ab 及 centos下单独安装方法
  3. Android开发之TextView高级应用
  4. docker学习笔记(四)——Dockerfile创建自定义镜像
  5. 【WPF】屏幕右下角消息提示框
  6. python37.dll可能与您正在运行_win7系统提示模块可能与您正在运行的windows版本不兼容如何解决...
  7. extern “C”
  8. Kali渗透测试工具库(三)hydra——密码暴力破解工具
  9. 技术沙龙|赋能企业数字化转型,移动云云原生应用架构实践
  10. Hibernate中的3中状态
  11. 字典哈希表的实现原理
  12. ansys16.0安装教程
  13. Sublime 安装Boxy + OmniMarkupPreviewer
  14. 内核热补丁,真的安全么?| 龙蜥技术
  15. 刚体运动学公式_理论力学:运动学
  16. 求两者较大值的max函数的用法(c++基础)
  17. 15年前,一则公路旁的Google的招聘广告
  18. ernel 3.10内核源码分析--KVM相关--虚拟机运行
  19. Tornadao—模板语法(控制语句)
  20. oracle安装时创建应答文件,12c 应答方式安装 (二) 创建cdb+pdb+netca

热门文章

  1. html图片怎么中心对齐,css图片居中(css怎么让图片水平居中对齐)
  2. 木偶然-2013.7.28
  3. php邮件程序,PHP发送电子邮件(Email)
  4. 八种你必须警惕的数据中心人身安全隐患
  5. mac 双击证书无法进入钥匙串(证书无法添加到钥匙串)
  6. polly php实例,亚马逊Amazon Polly文本转换语音PHP简明调用示例
  7. 2022全国职业技能大赛“信息安全管理与评估“--应急响应日志分析解析(高职组)
  8. HDU2571 命运(dp问题)
  9. 声卡无法识别和安装的解决方法
  10. android studio exclude,记录Android-Studio遇到的各种坑