python Mechanize follow_link 失败

标签 python hyperlink mechanize

我正在尝试在脚本中访问 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 中)。我哪里做错了,我怎样才能到达第二页及以后的页面?

最佳答案

不幸的是,该页面使用 Javascript 将 2459 字节的表单变量 POST 到服务器,只是为了导航到后续页面。以下是一些变量(我总共数了 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 以获取每个后续​​页面的结果(无需提取链接)。

更新 - 该站点完全是个麻烦事,但这里是一个基于 POST 的 2-N 页面的抓取。将 MAX_PAGE 设置为最高页码 + 1。该脚本将生成类似 file_000003.html 的文件。

注意:在使用之前,您需要将POSTDATA替换为contents of this paste blob (1 个月后到期)。它只是 Firebug 捕获的 POST 请求的主体,我用它来播种正确的参数:

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())

关于python Mechanize follow_link 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5859434/

相关文章:

python - 如何在Python代码中拥有cfile

html - 如何将多个链接放在同一行? (HTML5)

asp.net - 动态设置超链接控件的 NavigateUrl 属性内联

ruby - 如何获得PP在ruby中显示的结果

python - mechanize 的哪个功能与 urllib.urlencode 相同

python - Flask 路由规则作为函数参数

python - 在 Django ORM 中获取相关模型计数的有效方法

python - 如何在 matplotlib 中绘制双对数直方图

jquery - 定时 jquery/返回顶部 html css 链接

ruby - 使用 Mechanize 重定向到错误的 URI 会引发无效的 URI 错误