2017-02-02 6 views
2

Я пытаюсь программно очистить файлы с этой страницы: https://olms.dol-esa.gov/query/getYearlyData.do (да, возможно, было бы быстрее загрузить их вручную, но я хочу узнать, как это сделать).Сохранение файлов с помощью WWW :: Mechanize

У меня есть следующий фрагмент кода, чтобы попытаться, чтобы попытаться это на одном из файлов в качестве теста:

#!/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?

+0

Отключите JavaScript в своем браузере, и вы увидите, что страница без него бесполезна, поэтому WWW :: Mechanize отсутствует. Вместо использования WWW :: Mechanize :: Firefox вы должны увидеть, доступны ли данные через API; это почти всегда лучший выбор, чем соскабливание. [Здесь] (http://developer.dol.gov/) является главной страницей для API отдела труда. – ThisSuitIsBlackNot

+0

Да, я знаю, что страница отображается пустой, без включенного javascript.Тем не менее, исходный код все еще существует, и мне любопытно узнать, почему запрос POST с соответствующими полями, отправленными с запросом, не вызывает отправку сервера, особенно с помощью WWW :: Mechanize :: Firefox. – StevieD

+1

Посмотрите на источник с отключенным JS: элемент '

' отсутствует, поэтому 'submit_form' ничего не сделает. Поскольку W :: M :: F не работает, вы не задали параметр 'submitButton', и есть другие заголовки, которые вы не задали, которые могут потребоваться. Но опять же, это именно то, для чего нужны API; вы не должны быть свободны в кишках веб-страницы, сделанной для потребления человеком, потому что она может измениться в любое время и разбить ваш код миллионами разных способов. – ThisSuitIsBlackNot

ответ

1

В то время как комментарии ThisSuitIsBlackNot находятся на месте, существует довольно простой способ сделать это программно, не используя JS вообще. Вам даже не нужен WWW :: Mechanize.

Я использовал Web::Scraper, чтобы найти все файлы. Как вы сказали, значения формы есть. Это вопрос соскабливания их. WWW :: Механизм хорош в навигации, но не очень хорош при очистке. Web :: Интерфейс Scraper с другой стороны очень прост.

Как только у нас есть файлы, все, что нам нужно сделать, это отправить запрос POST с правильными значениями формы. Это очень похоже на WWW :: Mechanize's submit_form. Фактически, WWW :: Mechanize - это LWP::UserAgent под капотом, и все, что нам нужно, это запрос, поэтому мы используем его напрямую.

:content_file optionpost 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 
    ); 
} 

Как только вы запустите это, у вас будут все файлы в каталоге вашего скрипта. Это займет некоторое время, и нет выхода, но он работает.

Вам необходимо включить кнопку отправки в форму.

Поскольку вы хотели научиться делать что-то подобное, я построил его немного динамично. Действие формы также очищается, поэтому вы можете повторно использовать это в похожих формах, которые используют одни и те же имена форм (или делают это аргумент), и вам не нужно будет заботиться о действии формы. То же самое можно сделать и с кнопкой отправки, но вам нужно будет взять и атрибут name, и value.

Я буду повторять то, что ThisSuitIsBlackNot said in their comment: Скребок сайта всегда приходит с риском, что он изменится позже! Для одноразовой вещи, которая не имеет значения, если вы хотите запускать это как cronjob один раз в год, это может быть неудачно в следующем году, потому что они, наконец, обновили свой веб-сайт, чтобы быть немного более современным.

+1

Очень изобретательный. Я знаком с Web :: Scraper, но не думал использовать его, чтобы вытащить необходимые элементы формы. Я также не думал об использовании LWP :: UserAgent. Я узнал кое-что, что я искал. Благодаря! Да, я хорошо знаю ограничения соскабливания. Это больше академических упражнений, поэтому я могу отполировать свои навыки. – StevieD

+0

@StevieD рад, что я мог бы помочь. :) – simbabque