2011-05-02 5 views
2

NCBI 이미지 검색 페이지 (http://www.ncbi.nlm.nih.gov/images)의 검색 결과에 스크립트로 액세스하려고합니다. 나는 그것에게 수색 기간을 먹이고, 모든 결과에보고하고, 그 후에 다음 수색 기간에 그 후에 이동하고 싶다. 이렇게하려면 내가 첫 페이지 후 결과 페이지에 도착해야합니다, 그래서 나는 그것을 할 파이썬 기계화를 사용하려고 해요 : 변수에 (파이썬 기계어 follow_link가 실패합니다.

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) 

이 그냥 다시 검색 결과의 첫 페이지를 날 다시 제공 2 쪽). 내가 뭘 잘못하고 있고, 어떻게 그 두 번째 페이지와 그 이상으로 갈 수 있습니까?

답변

6

불행히도이 페이지는 다음 페이지로 이동하기 위해 Javascript를 사용하여 서버에 2459 바이트의 양식 변수를 POST합니다. 다음은 변수의 몇 가지 (I 총 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과 같은 파일을 생성합니다.

: 당신이 그것을 사용하기 전에, 당신은 (은 1 월에 만료)를 contents of this paste blob으로 POSTDATA를 교체해야합니다. 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()) 
+0

감사합니다. 나는 어떤 자바 스크립트도 모르므로 기계적으로 제공되는 POST 기능을 사용할 수 있습니까? 아니면 Javascript에서 뭔가를해야합니까? – andy

+0

그런데 이전에 wget을 사용하여 해당 변수에 대한 POST 데이터를 사용하여 시도했지만 기본적으로 동일한 동작을 얻었습니다. CurrPage 번호가 무엇이든 관계없이 항상 결과의 첫 번째 페이지가 표시됩니다. 당혹 스럽네. – andy

+0

mechanize에서 POST를 제출할 수 있습니다. 긁어 모으려고하는 사이트는 미친 짓을하고있는 것이므로 어떤 변수를 제출해야하는지 정확히 알아 내기 위해서는 다소 복잡 할 수 있습니다. 도움이 필요한 경우 mechanize로 POST를 수행하는 예를 사용하여 답변을 업데이트하겠습니다. – samplebias

관련 문제