Как мне использовать и отлаживать WWW :: Mechanize? - PullRequest
5 голосов
/ 09 июня 2009

Я очень новичок в Perl и учусь на лету, пока пытаюсь автоматизировать некоторые проекты для работы. До сих пор это было очень весело.

Я работаю над созданием отчета для клиента. Я могу получить этот отчет с веб-страницы, к которой я могу получить доступ. Сначала мне нужно будет заполнить форму с моим именем пользователя, паролем, выбрать сервер из выпадающего списка и войти в систему. Во-вторых, мне нужно нажать на ссылку для раздела отчета. В-третьих, необходимо заполнить форму для создания отчета.

Вот что я написал до сих пор:

my $mech = WWW::Mechanize->new();
my $url = 'http://X.X.X.X/Console/login/login.aspx';

$mech->get( $url );

$mech->submit_form(
     form_number => 1,
     fields      =>{
        'ctl00$ctl00$cphVeriCentre$cphLogin$txtUser'  => 'someone',
        'ctl00$ctl00$cphVeriCentre$cphLogin$txtPW'    => '12345',
        'ctl00$ctl00$cphVeriCentre$cphLogin$ddlServers'  => 'Live',
     button => 'Sign-In'
   },   
);
die unless ($mech->success);

$mech->dump_forms();

Я не понимаю, почему, но после этого я смотрю, что выводит дамп, и вижу код для первой страницы входа в систему, хотя я верю, что должен был перейти на следующую страницу после успешного входа в систему.

Может ли быть что-то с cookie, которое может повлиять на меня и попытку входа?

Что-то еще я делаю не так?

Ценю вашу помощь, Янов

Ответы [ 5 ]

6 голосов
/ 18 августа 2009

Это спустя несколько месяцев после факта, но я решил ту же проблему, основываясь на похожих вопросах, которые я задавал. См. Можно ли автоматизировать обратную передачу со стороны клиента? для получения дополнительной информации.

Вместо этого я использовал Python's Mechanize или Perl, но применяется тот же принцип.

Подводя итог моему предыдущему ответу:

Страницам ASP.NET требуется скрытый параметр под названием __EVENTTARGET в форме, который не будет существовать, если вы будете использовать механизацию в обычном режиме.

При посещении обычным пользователем на этих страницах есть функция __doPostBack ('foo'), которая присваивает релевантное значение __EVENTTARGET через событие onclick javascript на каждой из ссылок, но поскольку механизация не использует javascript, Вам нужно будет установить эти значения самостоятельно.

Ниже приведено решение Python, но его не должно быть слишком сложно адаптировать к Perl.

def add_event_target(form, target):
    #Creates a new __EVENTTARGET control and adds the value specified
    #.NET doesn't generate this in mechanize for some reason -- suspect maybe is 
    #normally generated by javascript or some useragent thing?
    form.new_control('hidden','__EVENTTARGET',attrs = dict(name='__EVENTTARGET'))
    form.set_all_readonly(False)
    form["__EVENTTARGET"] = target
2 голосов
/ 10 мая 2012

Если вы работаете в Windows, используйте Fiddler , чтобы увидеть, какие данные отправляются, когда вы выполняете этот процесс вручную, а затем используйте Fiddler, чтобы сравнить их с данными, полученными при выполнении вашим сценарием.

По моему опыту, прокси-сервер для отладки, такой как Fiddler , более полезен, чем Firebug, при проверке сообщений.

2 голосов
/ 09 июня 2009

Вы можете механизировать только то, что знаете. Прежде чем писать больше кода, я предлагаю вам использовать такой инструмент, как Firebug, и проверять, что происходит в вашем браузере, когда вы делаете это вручную.

Конечно, могут быть файлы cookie, которые используются. Или, может быть, вы забыли скрытый параметр формы? Только ты можешь сказать.

EDIT:

  • WWW :: Механизация должна заботиться о куки-файлах без какого-либо вмешательства.
  • Вы всегда должны проверять, были ли вызванные вами методы успешными. Первый get () работает?
  • Может быть полезно взглянуть на журналы сервера, чтобы увидеть, что на самом деле запрашивается и какой код состояния HTTP отправляется в ответ.
1 голос
/ 19 марта 2013

Мне показалось очень полезным использовать утилиту Wireshark при написании веб-автоматизации с WWW::Mechanize. Это поможет вам несколькими способами:

  1. Позволяет вам понять, был ли ваш запрос HTTP успешным или нет.
  2. См. Причину сбоя на уровне HTTP.
  3. Проследите точные данные, которые вы передаете на сервер, и посмотрите, что вы получите обратно.

Просто установите фильтр HTTP для сетевого трафика и запустите сценарий Perl.

0 голосов
/ 10 мая 2012

Очень короткая суть aspx-страниц в том, что они содержат всю локальную информацию о сеансе в паре переменных с префиксом "__" в общем aspxform. Обычно это форма верхнего уровня, и все элементы формы будут ее частью, но я думаю, что это может варьироваться в зависимости от реализации.

Для конкретной реализации, с которой я имел дело, мне нужно было позаботиться о 2 из этих переменных состояния, а именно:

__VIEWSTATE
__EVENTVALIDATION.

Ваша цель - убедиться, что эти переменные отправлены в форму, которую вы отправляете, поскольку они могут быть частью той основной формы aspxform, о которой я упоминал выше, и вы, вероятно, отправляете форму, отличную от этой.

Когда браузер загружает страницу aspx, часть javascript передает эту информацию о сеансе в рамках взаимодействия asp сервер / клиент, но, конечно, мы не можем позволить себе такую ​​роскошь с механизацией perl, поэтому вам придется вручную публиковать эти самостоятельно, добавив элементы в текущую форму с помощью mechanize.

В случае, который я только что решил, я в основном сделал это:

my $browser = WWW::Mechanize->new( );

# fetch the login page to get the initial session variables
my $login_page = 'http://www.example.com/login.aspx';
$response = $browser->get( $login_page);

# very short way to find the fields so you can add them to your post
$viewstate = ($browser->find_all_inputs( type => 'hidden', name => '__VIEWSTATE' ))[0]->value;
$validation = ($browser->find_all_inputs( type => 'hidden', name => '__EVENTVALIDATION' ))[0]->value;

# post back the formdata you need along with the session variables
$browser->post( $login_page, [ username => 'user', password => 'password, __VIEWSTATE => $viewstate, __EVENTVALIDATION => $validation ]);

# finally get back the content and make sure it looks right
print $response->content();
...