Лучший способ сканировать страницу с несколькими перенаправлениями
Я хочу просканировать веб-сайт NCBI и отправить запрос на выравнивание белка по этой ссылке: http://blast.ncbi.nlm.nih.gov/Blast.cgi?PROGRAM=blastp&BLAST_PROGRAMS=blastp&PAGE_TYPE=BlastSearch
Я хотел бы знать, могу ли я отправить запрос на этот адрес и получить результаты, которые появляются на новой странице, с использованием PHP. Там также есть проблема, прежде чем будут показаны окончательные результаты, страница подвергается нескольким перенаправлениям - вы можете проверить эту ситуацию, используя следующий ввод, который входит в текстовую область:
MHSSIVLATVLFVAIASASKTRELCMKSLEHAKVGTSKEAKQDGIDLYKHMFEHYPAMKKYFKHRENYTP
ADVQKDPFFIKQGQNILLACHVLCATYDDRETFDAYVGELMARHERDHVKVPNDVWNHFWEHFIEFLGSK
TTLDEPTKHAWQEIGKEFSHEISHHGRHSVRDHCMNSLEYIAIGDKEHQKQNGIDLYKHMFEHYPHMRKA
FKGRENFTKEDVQKDAFFVNKDTRFCWPFVCCDSSYDDEPTFDYFVDALMDRHIKDDIHLPQEQWHEFWK
LFAEYLNEKSHQHLTEAEKHAWSTIGEDFAHEADKHAKAEKDHHEGEHKEEHH
Вот моя попытка:
$link = 'http://blast.ncbi.nlm.nih.gov/Blast.cgi?
PROGRAM=blastp&BLAST_PROGRAMS=blastp&PAGE_TYPE=BlastSearch';
$request = array(
'http' => array(
'method' => 'POST',
'content' => http_build_query(array(
'QUERY' => $aaText
)
),
)
);
$context = stream_context_create($request);
$html = file_get_html($link, false, $context);
echo $html;
Этот код возвращает мне начальную страницу, как если бы POST не был выполнен. Спасибо
ОБНОВИТЬ
Я попробовал одно из предложений ниже - Гутта.
Вот мой новый код:
require_once 'goutte.phar';
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', $link);
$form = $crawler->selectButton('b1')->form();
$crawler = $client->submit($form, array('QUERY' => $aaTest));
echo $crawler->html();
переменная $aaTest
это последовательность белка, которую я дал выше. Хорошая часть: он публикует, получает новую страницу, но не следит за всеми перенаправлениями. Как я могу заставить его следовать всем перенаправлениям?
1 ответ
Я должен думать, что этот сайт очень полезен. Чтобы понять, что происходит, отключите JavaScript в вашем браузере и попробуйте просмотреть сайт (для этого я использую меню Disable->Disable JavaScript в Firebug, который является плагином Firefox).
Если вы перейдете к своей первой ссылке и вставите строку, вы получите форму в операции POST, которая фактически говорит о том, что ваш поиск выполняется. Это будет выглядеть примерно так:
Название работы: последовательность белка (333 буквы)
Идентификатор запроса: NR8ZP8E1071
Поскольку на этом экране нет большого интереса, я предполагаю, что вы не хотите копаться отсюда - но это то, что вы делаете в настоящее время.
Далее происходит то, что часть JavaScript представляет скрытую форму, используя этот код:
<SCRIPT LANGUAGE="JavaScript">
setTimeout('document.forms[0].submit();',1000);
</SCRIPT>
Я предполагаю, что во время большой нагрузки задержка здесь (в настоящее время установлена на 1000 мс, т.е. 1 секунда) немного увеличится. Скрытая форма выглядит так:
<form action="Blast.cgi" enctype="application/x-www-form-urlencoded" method="post" name="RequestFormat" id="RequestFormat"">
<input name="CMD" value="Get" type="hidden">
<input name="ALIGNMENTS" value="100" type="hidden">
<input name="ALIGNMENT_VIEW" value="Pairwise" type="hidden">
<input name="BLAST_PROGRAMS" value="blastp" type="hidden">
<input name="CDD_RID" value="data_cache_seq:180192" type="hidden">
<input name="CDD_SEARCH" value="on" type="hidden">
<input name="CDD_SEARCH_STATE" value="4" type="hidden">
<input name="CLIENT" value="web" type="hidden">
<input name="COMPOSITION_BASED_STATISTICS" value="2" type="hidden">
<input name="CONFIG_DESCR" value="2,3,4,5,6,7,8" type="hidden">
<input name="DATABASE" value="nr" type="hidden">
<input name="DESCRIPTIONS" value="100" type="hidden">
<input name="EQ_OP" value="AND" type="hidden">
<input name="EXPECT" value="10" type="hidden">
<input name="FILTER" value="F" type="hidden">
<input name="FORMAT_NUM_ORG" value="1" type="hidden">
<input name="FORMAT_OBJECT" value="Alignment" type="hidden">
<input name="FORMAT_TYPE" value="HTML" type="hidden">
<input name="FULL_DBNAME" value="nr" type="hidden">
<input name="GAPCOSTS" value="11 1" type="hidden">
<input name="GET_SEQUENCE" value="on" type="hidden">
<input name="HSP_RANGE_MAX" value="0" type="hidden">
<input name="JOB_TITLE" value="Protein Sequence (333 letters)" type="hidden">
<input name="LAYOUT" value="OneWindow" type="hidden">
<input name="LINE_LENGTH" value="60" type="hidden">
<input name="MASK_CHAR" value="2" type="hidden">
<input name="MASK_COLOR" value="1" type="hidden">
<input name="MATRIX_NAME" value="BLOSUM62" type="hidden">
<input name="MAX_NUM_SEQ" value="100" type="hidden">
<input name="MYNCBI_USER" value="9311188414" type="hidden">
<input name="NEW_VIEW" value="on" type="hidden">
<input name="NUM_DIFFS" value="0" type="hidden">
<input name="NUM_OPTS_DIFFS" value="0" type="hidden">
<input name="NUM_ORG" value="1" type="hidden">
<input name="NUM_OVERVIEW" value="100" type="hidden">
<input name="OLD_BLAST" value="false" type="hidden">
<input name="OLD_VIEW" value="false" type="hidden">
<input name="PAGE" value="Proteins" type="hidden">
<input name="PAGE_TYPE" value="BlastSearch" type="hidden">
<input name="PROGRAM" value="blastp" type="hidden">
<input name="QUERY_INDEX" value="0" type="hidden">
<input name="QUERY_INFO" value="Protein Sequence (333 letters)" type="hidden">
<input name="QUERY_LENGTH" value="333" type="hidden">
<input name="REPEATS" value="5755" type="hidden">
<input name="RID" value="NR8ZP8E1071" type="hidden">
<input name="RTOE" value="21" type="hidden">
<input name="SELECTED_PROG_TYPE" value="blastp" type="hidden">
<input name="SERVICE" value="plain" type="hidden">
<input name="SHORT_QUERY_ADJUST" value="on" type="hidden">
<input name="SHOW_LINKOUT" value="on" type="hidden">
<input name="SHOW_OVERVIEW" value="on" type="hidden">
<input name="USER_DEFAULT_MATRIX" value="4" type="hidden">
<input name="USER_DEFAULT_PROG_TYPE" value="blastp" type="hidden">
<input name="USER_TYPE" value="2" type="hidden">
<input name="WORD_SIZE" value="3" type="hidden">
<input name="db" value="protein" type="hidden">
<input name="stype" value="protein" type="hidden">
<input name="x" value="41" type="hidden">
<input name="y" value="12" type="hidden">
</form>
Это также создает запрос POST к программе, и наибольший интерес представляет поле RID
который связывает запрос с вашими начальными параметрами запроса. Это, вероятно, хранится в базе данных или временном файле, и ему присваивается идентификатор, срок действия которого истекает в течение нескольких часов.
Когда эта форма отправляется, предоставляется много интересной информации, представленной в запросе POST формы, которая ее создала. Возможно, что одно из приведенных выше полей указывает начальное количество отображаемых выравниваний. Затем, если вы снова включите JavaScript, вы обнаружите, что указание на конец страницы (а это уже несколько скриншотов) загрузит другой фрагмент с помощью этой программы:
Интересно, что здесь используется запрос GET. Используя сетевой монитор в Firefox, я запустил серию из них, чтобы посмотреть, смогу ли я определить последовательность возрастающих чисел. Я заметил что SEQ_LIST_START
начинается с 1 и увеличивается в блоках по 5, но я не уверен, где элементы в ALIGN_SEQ_LIST
исходит от - может быть, с текущей страницы. Это стоит того, чтобы вы сами посмотрели, можете ли вы заметить что-либо, тем более что вы поймете предмет так, как я не понимаю.
Возможно, вы сможете поработать с некоторыми параметрами строки запроса в этой ссылке, чтобы посмотреть, что контролирует количество возвращаемых элементов. Однако будьте осторожны: если вы запрашиваете гораздо больший набор, к которому привыкли их системы, вас могут заметить, и на вашем IP-адресе появится блок.
Кроме того, помните, что если вы сканируете веб-сайт, вы передаете свои расходы третьей стороне. Поскольку данные, по-видимому, доступны бесплатно, они будут в некоторой степени приемлемы для них и являются преимуществом уже потраченного финансирования. Однако следует помнить о нагрузке, которую вы помещаете на их сервер: не запрашивайте слишком большие порции и ставьте задержку в несколько секунд между каждым запросом.
Если вы планируете собирать огромную порцию данных (скажем, больше половины гигабайта), то чередуйте от нескольких секунд до пары минут ожидания или, возможно, сконцентрируйте свою загрузку ночью (их время), когда их серверы могут быть меньше занятый. Неспособность "действовать ответственно" в качестве сканера может привести ваш диапазон IP-адресов к их спискам блокировок, а в худшем случае может представлять собой атаку типа "отказ в обслуживании".
Итак, подведем итог, вот что вам нужно сделать:
- Сделайте начальный запрос POST, который получает форму
- Подожди несколько секунд
- Получите ответ (в частности, с идентификатором запроса) и повторно отправьте эти данные в новом POST
- Сбор данных с экрана
- Используйте GET-запросы во второй программе, чтобы получить новые данные
- Соберите новые данные из ответа
Будьте готовы поработать с параметрами POST и GET, чтобы увидеть эффект, и получайте удовольствие!