Скремблирование данных со всех страниц asp.net с использованием разбивки на страницы AJAX
Я хочу отменить веб-страницу, содержащую список пользователей с адресами, электронной почтой и т.д. веб-страница содержит список пользователей с разбиением на страницы, т.е. страница содержит 10 пользователей, когда я нажимаю ссылку на страницу 2, она будет загружать список пользователей с 2-й страницы через AJAX и обновить список так далее для всех ссылок на страницы.
Веб-сайт разработан на странице asp i.e с расширением .aspx, так как я ничего не знаю об asp.net и как asp управляет разбиением на страницы и AJAX
Я использую простой html dom http://sourceforge.net/projects/simplehtmldom/, чтобы ломать содержимое
для страниц, имеющих пользователей <=10
Мне не нужно симулировать запрос AJAX так же, как когда пользователь нажимает ссылку на паутину
но для страницы с разбиением на страницы, чтобы получить данные с других страниц, я имитирую пост AJAX-запрос
require 'simple_html_dom.php';
$html = file_get_html('www.example.com/user_list.aspx');
$viewstate = $html->find("#__VIEWSTATE");
$viewstate = $viewstate[0]->attr['value'];
$eventvalidation = $html->find("#__EVENTVALIDATION");
$eventvalidation = $eventvalidation[0]->attr['value'];
$number_of_pageinations = 3;
$pageNumberCodes = array(
'ctl00$cphMainContent$rdpMembers$ctl01$ctl01',
'ctl00$cphMainContent$rdpMembers$ctl01$ctl02',
'ctl00$cphMainContent$rdpMembers$ctl01$ctl03'
); // this code is added for each page in POST as __EVENTTARGET
for ($i = 0; $i < $number_of_pageinations; $i++) {
$options = array(
CURLOPT_RETURNTRANSFER => true, // return web page
CURLOPT_HEADER => false, // don't return headers
CURLOPT_ENCODING => "", // handle all encodings
CURLOPT_USERAGENT => "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7'", // who am i
CURLOPT_AUTOREFERER => true, // set referer on redirect
CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect
CURLOPT_TIMEOUT => 1120, // timeout on response
CURLOPT_MAXREDIRS => 10, // stop after 10 redirects
CURLOPT_POST => true,
CURLOPT_VERBOSE => true,
CURLOPT_POSTFIELDS => urlencode('ctl00%24scriptManager=ctl00%24cphMainContent%24ctl00%24cphMainContent%24rdpMembersPanel%7C' . $pageNumberCodes[0] . '&__EVENTTARGET=' . $pageNumberCodes[0] . '&__EVENTARGUMENT=' . '&__VIEWSTATE=' . $viewstate . '&__EVENTVALIDATION=' . $eventvalidation . "&google=" . '&ctl00%24cphMainContent%24txtZip=' . '&ctl00%24cphMainContent%24cboRadius=Exact' . '&ctl00%24cphMainContent%24txtMemberName=' . '&ctl00%24cphMainContent%24txtCity=Honolulu' . '&ctl00%24cphMainContent%24cboState=HI' . '&ctl00%24cphMainContent%24txtAddress=' . '&ctl00_cphMainContent_rdpMembers_ClientState=' . '&ctl00%24cphMainContent%24ddList=-Select%20field%20to%20sort-' . '&ctl00_cphMainContent_ddList_ClientState=' . '&ctl00_cphMainContent_rdlMembers_ClientState=' . '&ctl00_cphMainContent_ddList_ClientState=' . '&ctl00_cphMainContent_rdlMembers_ClientState=' . '&ctl00_cphMainContent_rdpMembers1_ClientState=' . '&__ASYNCPOST=true' . 'RadAJAXControlID=ctl00_cphMainContent_RadAjaxManager1')
);
$ch = curl_init($url);
curl_setopt_array($ch, $options);
$return = curl_exec($ch);
curl_close($ch);
echo $return;
$newHtml = str_get_html($return);
$viewstate = $newHtml->find("#__VIEWSTATE");
$viewstate = $viewstate[0]->attr['value'];
$eventvalidation = $newHtml->find("#__EVENTVALIDATION");
$eventvalidation = $eventvalidation[0]->attr['value'];
}
это должно отражать данные с разных страниц, но всегда печатает данные первой страницы, может ли кто-нибудь указать мне, где я нахожусь, а что отсутствует
Я не знаю, как asp управляет разбиением на страницы и запросом AJAX, а что __EVENTARGUMENT
, __VIEWSTATE
и __EVENTVALIDATION
Ответы
Ответ 1
В общем, чтобы подделать веб-сайт ASP.NET, чтобы думать, что вы на самом деле нажали кнопку (в более общих терминах - выполнили обратную передачу), вам нужно сделать следующее:
-
Получите значение каждого элемента INPUT и SELECT на странице. Это может не потребоваться в каждом сценарии, но вы всегда должны по крайней мере получать значения всех скрытых полей, где имя начинается с "__" (например, __VIEWSTATE). Вам действительно не нужно знать, что на них написано - просто чтобы значение в них было отправлено обратно на сервер без изменений.
-
Создайте запрос POST на сервер. Вам нужно использовать классический POST, избегая любых запросов AJAX. Используя некоторые браузерные плагины (в Firefox или Chrome), возможно, можно отключить XMLHttpRequest, чтобы затем перехватить запрос без AJAX с помощью инструментов, таких как Fiddler.
-
Добавьте каждое значение из # 1 в этот почтовый запрос. Для перезаписывания требуется только два значения: __EVENTTARGET и __EVENTARGUMENT. Вы оставите их пустыми, за исключением того, что ссылка или кнопка, которую вы пытаетесь имитировать, имеет обработчик onclick
, такой как <a href="javascript:__doPostBack('ctl00$login','')">
. Если это так, проанализируйте значения из этой ссылки - первая - это цель события (обычно она будет соответствовать идентификатору какого-либо элемента на странице), второй - аргумент события.
-
Если вы правильно выполнили запрос, вам нужно вернуть HTML-страницу. Если вы получите частичный ответ, проверьте, не прошел ли HTTP-заголовок, который запрашивает результат async.
Ответ 2
Мой лучший совет - использовать iMacros https://addons.mozilla.org/en-US/firefox/addon/imacros-for-firefox/
iMacros:
Независимо от того, является ли это ajax -.aspx,.jsp или .php.
Ответ 3
Я бы рекомендовал разветкиться на Ruby и попробовать Capybara, который является разумным способом использования Selenium. Он позволяет вам посещать страницу, а затем проверять фактическую DOM. Вы можете нажать на все, дождаться событий и т.д. Он использует настоящий браузер.
visit "http://www.google.com"
page.find("button[name=btnK]")
Ответ 4
Я получил некоторый тестовый код, работающий с использованием вашего в качестве основы, и единственная проблема, которую я нашел, - это строка.
CURLOPT_POSTFIELDS => urlencode('ctl00%24scriptManager=ctl00%24cphMainContent%24ctl00%24cphMainContent%24rdpMembersPanel%7C' . $pageNumberCodes[0] . '&__EVENTTARGET=' . $pageNumberCodes[0] . '&__EVENTARGUMENT=' . '&__VIEWSTATE=' . $viewstate . '&__EVENTVALIDATION=' . $eventvalidation . "&google=" . '&ctl00%24cphMainContent%24txtZip=' . '&ctl00%24cphMainContent%24cboRadius=Exact' . '&ctl00%24cphMainContent%24txtMemberName=' . '&ctl00%24cphMainContent%24txtCity=Honolulu' . '&ctl00%24cphMainContent%24cboState=HI' . '&ctl00%24cphMainContent%24txtAddress=' . '&ctl00_cphMainContent_rdpMembers_ClientState=' . '&ctl00%24cphMainContent%24ddList=-Select%20field%20to%20sort-' . '&ctl00_cphMainContent_ddList_ClientState=' . '&ctl00_cphMainContent_rdlMembers_ClientState=' . '&ctl00_cphMainContent_ddList_ClientState=' . '&ctl00_cphMainContent_rdlMembers_ClientState=' . '&ctl00_cphMainContent_rdpMembers1_ClientState=' . '&__ASYNCPOST=true' . 'RadAJAXControlID=ctl00_cphMainContent_RadAjaxManager1')
потребуется, чтобы urlencode перемещался так, чтобы выглядеть так
CURLOPT_POSTFIELDS => 'ctl00%24scriptManager=ctl00%24cphMainContent%24ctl00%24cphMainContent%24rdpMembersPanel%7C' . $pageNumberCodes[0] . '&__EVENTTARGET=' . $pageNumberCodes[0] . '&__EVENTARGUMENT=' . '&__VIEWSTATE=' . rawurlencode($viewstate) . '&__EVENTVALIDATION=' . rawurlencode($eventvalidation) . "&google=" . '&ctl00%24cphMainContent%24txtZip=' . '&ctl00%24cphMainContent%24cboRadius=Exact' . '&ctl00%24cphMainContent%24txtMemberName=' . '&ctl00%24cphMainContent%24txtCity=Honolulu' . '&ctl00%24cphMainContent%24cboState=HI' . '&ctl00%24cphMainContent%24txtAddress=' . '&ctl00_cphMainContent_rdpMembers_ClientState=' . '&ctl00%24cphMainContent%24ddList=-Select%20field%20to%20sort-' . '&ctl00_cphMainContent_ddList_ClientState=' . '&ctl00_cphMainContent_rdlMembers_ClientState=' . '&ctl00_cphMainContent_ddList_ClientState=' . '&ctl00_cphMainContent_rdlMembers_ClientState=' . '&ctl00_cphMainContent_rdpMembers1_ClientState=' . '&__ASYNCPOST=true' . 'RadAJAXControlID=ctl00_cphMainContent_RadAjaxManager1'