文章插图
3种抓取其中数据的方法 。首先是正则表达式,然后是流行的BeautifulSoup模块,最后是强大的lxml模块 。
1 正则表达式如果你对正则表达式还不熟悉,或是需要一些提示,那么你可以查阅http://docs.python.org/2/howto/regex.html获得完整介绍 。即使你使用过其他编程语言的正则表达式,我依然推荐你一步一步温习一下Python中正则表达式的写法 。
由于每章中都可能构建或使用前面章节的内容,因此我建议你按照类似本书代码库的文件结构进行配置 。所有代码都可以从代码库的code目录中运行,以便导入工作正常 。如果你希望创建一个不同的结构,请注意需要变更所有来自其他章的导入操作(比如下述代码中的from chp1.advanced_link_crawler) 。
当我们使用正则表达式抓取国家(或地区)面积数据时,首先需要尝试匹配``元素中的内容,如下所示 。
>>> 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']这个迭代版本看起来更好一些,但是网页更新还有很多其他方式,同样可以让该正则表达式无法满足 。比如,将双引号变为单引号,`标签之间添加多余的空格,或是变更area_label`等 。下面是尝试支持这些可能性的改进版本 。
>>> re.findall('''.*?(.*?)''', html)['244,820 square kilometres']虽然该正则表达式更容易适应未来变化,但又存在难以构造、可读性差的问题 。此外,还有很多其他微小的布局变化也会使该正则表达式无法满足,比如在`标签里添加title属性,或者tr、td`元素修改了它们的CSS类或ID 。
从本例中可以看出,正则表达式为我们提供了抓取数据的快捷方式,但是该方法过于脆弱,容易在网页更新后出现问题 。幸好,还有更好的数据抽取解决方案,比如我们将在本章介绍的其他抓取库 。
2 Beautiful SoupBeautiful Soup
是一个非常流行的Python库,它可以解析网页,并提供了定位内容的便捷接口 。如果你还没有安装该模块,可以使用下面的命令安装其最新版本 。
pip install beautifulsoup4使用Beautiful Soup的第一步是将已下载的HTML内容解析为soup文档 。由于许多网页都不具备良好的HTML格式,因此Beautiful Soup需要对其标签开合状态进行修正 。例如,在下面这个简单网页的列表中,存在属性值两侧引号缺失和标签未闭合的问题 。
- Area
- Population
>>> from bs4 import BeautifulSoup>>> from pprint import pprint>>> broken_html = '
- Area
- Population
- Area
- Population
pip install html5lib现在,我们可以重复这段代码,只对解析器做如下变更 。
>>> soup = BeautifulSoup(broken_html, 'html5lib')>>> fixed_html = soup.prettify()>>> pprint(fixed_html)
- Area
- Population
现在,我们可以使用find()和find_all()方法来定位我们需要的元素了 。
>>> ul = soup.find('ul', attrs={'class':'country_or_district'})>>> ul.find('li') # returns just the first match
想要了解可用方法和参数的完整列表,请访问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 LxmlLxml
是基于libxml2这一XML解析库构建的Python库,它使用C语言编写,解析速度比Beautiful Soup更快,不过安装过程也更为复杂,尤其是在Windows中 。最新的安装说明可以参考http://lxml.de/installation.html 。如果你在自行安装该库时遇到困难,也可以使用Anaconda来实现 。
你可能对Anaconda不太熟悉,它是由Continuum Analytics公司员工创建的主要专注于开源数据科学包的包和环境管理器 。你可以按照其安装说明下载及安装Anaconda 。需要注意的是,使用Anaconda的快速安装会将你的PYTHON_PATH设置为Conda的Python安装位置 。
和Beautiful Soup一样,使用lxml模块的第一步也是将有可能不合法的HTML解析为统一格式 。下面是使用该模块解析同一个不完整HTML的例子 。
>>> from lxml.html import fromstring, tostring>>> broken_html = '
- Area
- Population
- Area
- Population
解析完输入内容之后,进入选择元素的步骤,此时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【如何抓取别人网页的数据?3种网页抓取方法】通过对代码树使用cssselect方法,我们可以利用CSS语法来选择表格中ID为places_area__row的行元素,然后是类为w2p_fw的子表格数据标签 。由于cssselect返回的是一个列表,我们需要获取其中的第一个结果,并调用text_content方法,以迭代所有子元素并返回每个元素的相关文本 。在本例中,尽管我们只有一个元素,但是该功能对于更加复杂的抽取示例来说非常有用 。
- 如何成为百度推广代理?百度推广开户条件有哪些
- 如何分析基金数据?大数据时代基金数据分析
- 如何写原创内容,这三个方法不错!
- 如何外贸网络推广?5种策略实现外贸精准推广
- 百度如何引流推广?教你如何轻松做百度文库推广引流?
- 网站流量如何提高?18个细节轻松提升你的网站流量
- 网站权重如何查询?怎样判断网站权重是否真实
- 枇杷采后如何正确管理,枇杷采后管理方法
- 铜钱草怎么种植 如何种植长得旺盛
- 薰衣草植物图片 薰衣草养殖