使用WWW :: Mechanize保存文件

时间:2017-02-02 23:08:01

标签: perl web-scraping www-mechanize

我正在尝试以编程方式抓取此页面中的文件:https://olms.dol-esa.gov/query/getYearlyData.do(是的,手动下载它们可能会更快,但我想学习如何执行此操作)。

我有以下一些代码尝试在其中一个文件上尝试这个作为测试:

#!/usr/bin/perl
use strict;
use warnings;
use WWW::Mechanize; 

my $mech = WWW::Mechanize->new;

$mech->get( 'https://olms.dol-esa.gov/query/getYearlyData.do' );
print $mech->uri();
$mech->submit_form( with_fields => { selectedFileName => '/filer/local/cas/YearlyDataDump/2000.zip' } );

当我运行代码时,没有任何反应。什么都没下载。思考javascript可能是问题,我也尝试使用WWW :: Mechanize :: Firefox相同的代码。再一次,当我运行代码时没有任何反应。

我也没有看到文件的路径。它可能在一些javascript中模糊不清。

那么获取这些文件的最佳方法是什么?是不是可以在没有javascript的情况下获取它们?

1 个答案:

答案 0 :(得分:1)

虽然ThisSuitIsBlackNot的评论是现实的,但有一种相当简单的方法可以在不使用JS的情况下以编程方式执行此操作。你甚至不需要WWW :: Mechanize。

我已使用Web::Scraper查找所有文件。如你所说,表格价值就在那里。这是一个刮掉它们的问题。 WWW :: Mechanize擅长导航,但不是很擅长刮擦。另一方面,Web :: Scraper的界面非常简单。

获得文件后,我们需要做的就是提交一个包含正确表单值的POST请求。这与WWW :: Mechanize的submit_form非常相似。事实上,WWW :: Mechanize是一个LWP::UserAgent,我们需要的只是一个请求,所以我们可以直接使用它。

:content_file option上的post method告诉它将响应放入文件中。它将使用ZIP文件做正确的事情并自动将其写为二进制文件。

use strict;
use warnings;
use LWP::UserAgent;
use Web::Scraper;
use URI;

# build a Web::Scraper to find all files on the page
my $files = scraper {
    process 'form[name="yearlyDataForm"]',    'action'  => '@action';
    process 'input[name="selectedFileName"]', 'files[]' => '@value';
};

# get the files and the form action
my $res = $files->scrape( URI->new('https://olms.dol-esa.gov/query/getYearlyData.do') );

# use LWP to download them one by one
my $ua = LWP::UserAgent->new;
foreach my $path ( @{ $res->{files} } ) {

    # the file will end up relative to the current working directory (.)
    ( my $filename ) = ( split '/', $path )[-1];

    # the submit is hardcoded, but that could be dynamic as well
    $ua->post(
        $res->{action},
        { selectedFileName => $path, submitButton => 'Download' },
        ':content_file' => $filename # this downloads the file
    );
}

运行此脚本后,您将拥有脚本目录中的所有文件。它需要一点时间,没有输出,但它有效。

您需要确保在表单中包含提交按钮。

既然你想学习如何做这样的事情,我已经建立了一点动态。表单操作也被删除,因此您可以在使用相同表单名称(或使其成为参数)的类似表单上重用此表单,并且您不必关心表单操作。使用提交按钮也可以完成相同的操作,但您需要同时获取namevalue属性。

我会重复ThisSuitIsBlackNot said in their comment的内容:抓一个网站总会带来以后更改的风险!对于一次性无关紧要的事情,如果你愿意的话我希望每年一次作为cronjob运行它可能已经在明年失败,因为他们最终更新了他们的网站,使其更加现代化。