网页爬取是一种从网页上检索数据的技术。它可以手动完成,但通常是通过编程完成。有大量的原因,有人可能会爬取一个网站。
- 为市场营销创造线索
- 监测页面上的价格(并在价格降到低点时购买)。
- 学术研究
- 套利投注
由于网络爬取非常普遍,任何能够发出HTTP/S请求并解析网页上的标记的编程语言都可以进行爬取。Perl就是这样一种语言。在网络的一些角落里,Perl被称为 “编程的瑞士军刀”,它被用于一些任务,如数据库编程、游戏开发、网络开发和爬取。
本条规定。
- 网络爬取的简要介绍
- 关于爬取的好处的讨论
- 并演示了如何用Perl建立一个简单的爬取器。
网页爬取的应用
我们已经在前面讨论了爬取的一些好处,但这个清单并不详尽。
网页爬取器可以填补API响应数据的空白,并检索API维护者没有包括的数据。例如,Genius API没有将歌词作为其API响应的一部分来发送–本文将告诉你如何通过爬取来解决这个问题。
信息收集是爬取法填补这些空白的一个重要部分。一些公司爬取他们的竞争对手的网站,以确保他们的产品提供良好的价格,不被压价。或者,他们可能会爬取多个评论其产品的网页,并将它们汇总到一个共享文件中,以便于查看。
爬取的应用几乎是无止境的,因为一个公司从互联网上(几乎)任何地方检索数据所能获得的洞察力和价值是巨大的。
cURL
爬取的最简单示范是对一个网站的cURL请求。
$ curl -i -v -X GET https://genius.com
服务器响应,基本上是由Genius登陆页面上的标记和定义响应头组成,如下所示:
除了HTML,我们还有genius.com回应的HTTP头信息,如内容类型、cookies和缓存。
内容类型,也被称为MIME类型,是响应的数据格式,在这个例子中是HTML。
在这种情况下,HTTP cache-control头是一组指令,用于说明需要如何进行缓存。在我们上面的响应中,这些指令表明HTML可以被缓存180秒。
Cookies是包含数据的短字符串,从服务器发送到客户端的Set-Cookie头。服务器头,像用户代理一样,标识了服务器。如果你想知道更多关于这个响应中没有详细讨论的元数据的部分,你可以访问MDN。
用Perl抓取网页
你将要建立的爬取器的目标是为Genius上的指定歌曲获取歌词。这很有用,因为Genius REST API中的歌曲资源并不包括歌词。为了实现这一目标,你需要安装Perl的HTML TreeBuilder模块,并将其与Library for the World Wide Web in Perl(LWP)模块一起使用。
LWP
Perl的Library for WWW in Perl(LWP)是一套语言API(类和函数),用于编写访问网络数据的HTTP客户端。该库在大多数Perl发行版中都是开箱即用,并支持广泛的HTTP功能,如多方法HTTP请求和文档及文件下载,甚至为CPAN等语言包管理器提供支持。
你可以在Perl综合档案网(CPAN)上找到完整的LWP API规范,或者在你选择的控制台中输入以下内容,用perldoc在本地浏览它。
$ perldoc LWP
用TreeBuilder进行解析
HTML::Treebuilder是CPAN上托管的一个Perl模块,其主要职责是构建HTML树,以便进行额外的选择性解析。它使用了几种方法来构建HTML文档和从它所使用的HTML::Parser和HTML::Element包中衍生出来的标记穿插字符串。
你可以用cpan
或cpanm
来安装TreeBuilder,根据CPAN官方网站上的指南,这两种方法都可以在大多数主流操作系统上安装。在cpan
REPL中(在初次使用前可能需要额外的配置,因为你可能需要启用readline包支持以简化控制台输入的格式化,并为所有通过REPL安装的Perl模块指定一个基本目录),以下指令应该足够了。
$ cpan cpan[1]> install HTML::TreeBuilder
或者,用cpanm
,即类似
于JavaScript的npm和PHP的Composer的minified版本,按以下方式安装TreeBuilder。
$ cpanm HTML::TreeBuilder
爬虫的编码
在这个例子中,我们要检索美国作曲家DJ Shadow的《Six Days》的歌词。
第一步是操作LWP和TreeBuilder库,分别发出HTTPGET
请求(并有效地从Genius中提取歌词数据),并让爬取器解析产生的HTML。
my $ua = LWP::UserAgent->new; $ua->agent("Genius Scraper"); my $url = "https://genius.com/DJ-Shadow-Six-Days-lyrics"; my $root = HTML::TreeBuilder->new(); # perform HTTP GET request my $request = $ua->get($url) or die "Cannot contact Genius $!\n";
下一步是解析由托管Genius应用的服务器返回的标记。在这种情况下,解析意味着将标记编码为一个可遍历的树状结构。为了在请求成功的情况下避免任何Perl编码错误,你应该向解析器的解析方法提供从请求返回的标记的UTF-8解码版本。
if ($request->is_success) { $root->parse(decode_utf8 $request->content); } else { # print error message print "Cannot display the lyrics.\n"; }
在完成解析后,你将调用TreeBuilder API中定义的look_down方法来遍历结果标记并提取歌词。在Genius平台上发布的歌词驻留在一个被称为歌词根的 div元素中。要继续下去,你必须对上述规定进行编码,以产生类似下面的片段的东西:
my $data = $root->look_down( _tag => "div", id => "lyrics-root" );
虽然在调试树形遍历时非常有用,但TreeBuilder的倾倒方法(继承自HTMLBuilder模块)并没有为标记格式化提供最好的用户界面。另一方面,FormatText模块中的基元对于整齐地显示从HTTP响应中产生的标记是最有用的。
要把产生的HTML子树打印成整齐的字符串输出,你只需要实例化FormatText,并以数据为唯一参数调用其格式方法:
my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 50); $formatter->format($data);
现在你可以通过在控制台中输入以下内容来运行爬取器:
$ chmod a+x scraper.pl && ./scraper.pl
控制台中的输出应该出现在下面的片段中:
Six Days Lyrics --------------- [Verse 1] At the starting of the week At summit talks you'll hear them speak It's only Monday Negotiations breaking down See those leaders start to frown It's sword and gun day [Hook] Tomorrow never comes until it's too late ... etc. etc.
在这一点上,爬取器正在爬行页面,以检索 “Six Days “的歌词。
为了增加一些亮点,提高它的解析能力,以适应Genius平台上托管的任何歌曲,你可以用一个命令行参数–与歌曲输入有关的参数对脚本的每个调用进行参数化。
if ($#ARGV + 1 != 1) { die "Please provide song input\n"; }
随之而来的是URL的改变,以完成解析器:
my $url = "https://genius.com/$ARGV[0]";
现在,你已经完成了大部分艰苦的工作,你可以调用Genius刮刀,通过输入以下内容提取歌曲 “Six Days “的歌词:
$ ./scraper.pl DJ-shadow-Six-Days-lyrics [文中代码源自Scrapingbee]
搜集器的代码可在GitHub的Gist中找到。你可以自由地定制你认为合适的代码。
总 结
爬取网络包括检索网络资源的内容,通常是网页。它有许多用途,包括个人开发者和大型企业项目,从填补API响应数据的空白到增强商业智能。由于爬取在很大程度上依赖于通过HTTP传送的标记,任何能够进行HTTP客户端请求并解析所产生的HTML的语言都可以利用这种技术来获取数据,而Perl是这些语言中最强大的一种。
本文首先介绍了网页爬取及其潜在用途,然后解释了你如何使用Perl构建一个简单的Genius爬取器,以减轻服务的API中的低效率。这个教程应该为你刻意应用网页爬取和收获数据提供坚实的基础,以达到自己的目的。