繁体   English   中英

使用 WWW::Mechanize 保存文件

[英]Saving files with 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 的情况下获得它们?

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

我使用Web::Scraper来查找所有文件。 正如您所说,表单值就在那里。 这是把它们刮掉的问题。 WWW::Mechanize 擅长导航,但不太擅长抓取。 另一方面,Web::Scraper 的界面非常简单。

一旦我们有了文件,我们需要做的就是提交一个带有正确表单值的 POST 请求。 这与 WWW::Mechanize 的submit_form非常相似。 实际上,WWW::Mechanize 背后是一个LWP::UserAgent ,我们只需要一个请求,就可以直接使用它。

post方法上的:content_file选项告诉它将响应放入文件中。 它会对 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 在他们的评论中所说的话抓取网站总是伴随着以后更改的风险! 对于一次无关紧要的事情,如果您想每年将其作为 cronjob 运行一次,那么明年可能已经失败,因为他们最终更新了他们的网站,使其更加现代。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM