python Mechanize follow_link не работает

Я пытаюсь получить доступ к результатам поиска на странице поиска изображений NCBI (http://www.ncbi.nlm.nih.gov/images) в скрипте. Я хочу скормить ему поисковый запрос, сообщить обо всех результатах, а затем перейти к следующему поисковому запросу. Для этого мне нужно перейти к страницам результатов после первой страницы, поэтому я пытаюсь использовать python Mechanize для этого:

import mechanize
browser=mechanize.Browser()
page1=browser.open('http://www.ncbi.nlm.nih.gov/images?term=drug')
a=browser.links(text_regex='Next')
nextlink=a.next()
page2=browser.follow_link(nextlink)

Это просто снова возвращает мне первую страницу результатов поиска (в переменной page2). Что я делаю не так и как мне перейти на эту вторую страницу и дальше?


person andy    schedule 02.05.2011    source источник


Ответы (1)


К сожалению, эта страница использует Javascript для отправки 2459 байтов переменных формы на сервер, просто чтобы перейти на следующую страницу. Вот несколько переменных (всего я насчитал 38 варов):

EntrezSystem2.PEntrez.ImagesDb.Images_SearchBar.Term=drug
EntrezSystem2.PEntrez.ImagesDb.Images_SearchBar.CurrDb=images
EntrezSystem2.PEntrez.ImagesDb.Images_ResultsPanel.Entrez_Pager.CurrPage=2

Вам нужно будет создать POST-запрос к серверу, содержащий некоторые или все эти переменные. К счастью, если он работает для страницы 2, вы можете просто увеличить CurrPage и отправить еще один POST для получения каждой последующей страницы результатов (нет необходимости извлекать ссылки).

Обновление. Этот сайт - сплошная заноза, но вот анализ 2-N страниц на основе POST. Установите MAX_PAGE на самый высокий номер страницы + 1. Сценарий будет создавать файлы типа file_000003.html.

Примечание. Перед использованием вам необходимо заменить POSTDATA на содержимое этого вставляемого большого двоичного объекта (истекает через 1 месяц). Это просто тело запроса POST, захваченное Firebug, которое я использую для заполнения правильных параметров:

import cookielib
import json
import mechanize
import sys
import urllib
import urlparse

MAX_PAGE = 6
TERM = 'drug'
DEBUG = False

base_url = 'http://www.ncbi.nlm.nih.gov/images?term=' + TERM
browser = mechanize.Browser()
browser.set_handle_robots(False)
browser.set_handle_referer(True)
browser.set_debug_http(DEBUG)
browser.set_debug_responses(DEBUG)
cjar = cookielib.CookieJar()
browser.set_cookiejar(cjar)

# make first GET request. this will populate the cookie
res = browser.open(base_url)

def write(num, data):
    with open('file_%06d.html' % num, 'wb') as out:
        out.write(data)

def encode(kvs):
    res = []
    for key, vals in kvs.iteritems():
        if isinstance(vals, list):
            for v in vals:
                res.append('%s=%s' % (key, urllib.quote(v)))
        else:
            res.append('%s=%s' % (key, urllib.quote(vals)))
    return '&'.join(res)

write(1, res.read())

# set this var equal to the contents of this: http://pastebin.com/UfejW3G0
POSTDATA = '''<post data>'''

# parse the embedded json vars into POST parameters
PREFIX1 = 'EntrezSystem2.PEntrez.ImagesDb.'
PREFIX2 = 'EntrezSystem2.PEntrez.DbConnector.'
params = dict((k, v[0]) for k, v in urlparse.parse_qs(POSTDATA).iteritems())

base_url = 'http://www.ncbi.nlm.nih.gov/images'
for page in range(2, MAX_PAGE):
    params[PREFIX1 + 'Images_ResultsPanel.Entrez_Pager.CurrPage'] = str(page)
    params[PREFIX1 + 'Images_ResultsPanel.Entrez_Pager.cPage'] = [str(page-1)]*2

    data = encode(params)
    req = mechanize.Request(base_url, data)
    cjar.add_cookie_header(req)
    req.add_header('Content-Type', 'application/x-www-form-urlencoded')
    req.add_header('Referer', base_url)
    res = browser.open(req)

    write(page, res.read())
person samplebias    schedule 02.05.2011
comment
Спасибо за помощь. Я не знаю никакого Javascript, поэтому могу ли я использовать некоторые возможности POST, предоставляемые Mechanize, или мне нужно что-то делать в Javascript? - person andy; 02.05.2011
comment
Кстати, ранее я пробовал использовать wget и curl с данными POST для этих переменных и получил в основном то же поведение: всегда получаю только первую страницу результатов, независимо от того, какой номер CurrPage я передал. Это сбивает с толку. - person andy; 02.05.2011
comment
Вы можете отправить сообщение с сайта Mechanize. Сайт, который вы пытаетесь очистить, делает некоторые сумасшедшие вещи, поэтому может потребоваться немного времени, чтобы точно определить, какие переменные необходимо отправить. Я дополню свой ответ примером выполнения POST с помощью Mechanize, если это поможет. - person samplebias; 04.05.2011