2016-12-14 2 views
0

Ceci est un suivi d'une question que j'ai vue plus tôt aujourd'hui. Dans cette question, un utilisateur demande à un problème de télécharger un pdf de cette url:Téléchargement de fichier avec urllib2 vs demandes: Pourquoi ces sorties sont-elles différentes?

http://journals.sagepub.com/doi/pdf/10.1177/0956797614553009

Je pense que les deux fonctions de téléchargement ci-dessous va donner le même résultat, mais la version urllib2 télécharge, html avec tag de script référençant un chargeur pdf, tandis que la version requests télécharge le pdf réel. Quelqu'un peut-il expliquer la différence de comportement?

import urllib2 
import requests 

def get_pdf_urllib2(url, outfile='ex.pdf'): 
    resp = urllib2.urlopen(url) 
    with open(outfile, 'wb') as f: 
     f.write(resp.read()) 

def get_pdf_requests(url, outfile='ex.pdf'): 
    resp = requests.get(url) 
    with open(outfile, 'wb') as f: 
     f.write(resp.content) 

est-requests assez intelligent pour attendre des sites Web dynamiques pour rendre avant de télécharger?

Modifier Faisant suite à l'idée de @ cwallenpoole, j'ai comparé les en-têtes et essayé la permutation des en-têtes de la requête requests dans la demande urllib2. L'en-tête magique était Cookie; les fonctions ci-dessous écrivent le même fichier pour l'exemple d'URL.

def get_pdf_urllib2(url, outfile='ex.pdf'): 
    req = urllib2.request(url, headers={'Cookie':'I2KBRCK=1'}) 
    resp = urllib2.urlopen(req) 
    with open(outfile, 'wb') as f: 
     f.write(resp.read()) 

def get_pdf_requests(url, outfile='ex.pdf'): 
    resp = requests.get(url) 
    with open(outfile, 'wb') as f: 
     f.write(resp.content) 

question suivante: où est-ce cookie requests obtenir? Est-ce que requests effectue plusieurs voyages vers le serveur?

Edit 2 Cookie est venu d'un en-tête de redirection:

>>> handler=urllib2.HTTPHandler(debuglevel=1) 
>>> opener=urllib2.build_opener(handler) 
>>> urllib2.install_opener(opener) 
>>> respurl=urllib2.urlopen(req1) 
send: 'GET /doi/pdf/10.1177/0956797614553009 HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: journals.sagepub.com\r\nConnection: close\r\nUser-Agent: Python-urllib/2.7\r\n\r\n' 
reply: 'HTTP/1.1 302 Found\r\n' 
header: Server: AtyponWS/7.1 
header: P3P: CP="NOI DSP ADM OUR IND OTC" 
header: Location: http://journals.sagepub.com/doi/pdf/10.1177/0956797614553009?cookieSet=1 
header: Set-Cookie: I2KBRCK=1; path=/; expires=Thu, 14-Dec-2017 17:28:28 GMT 
header: Content-Type: text/html; charset=utf-8 
header: Content-Length: 110 
header: Connection: close 
header: Date: Wed, 14 Dec 2016 17:28:28 GMT 
send: 'GET /doi/pdf/10.1177/0956797614553009?cookieSet=1 HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: journals.sagepub.com\r\nConnection: close\r\nUser-Agent: Python-urllib/2.7\r\n\r\n' 
reply: 'HTTP/1.1 302 Found\r\n' 
header: Server: AtyponWS/7.1 
header: Location: http://journals.sagepub.com/action/cookieAbsent 
header: Content-Type: text/html; charset=utf-8 
header: Content-Length: 85 
header: Connection: close 
header: Date: Wed, 14 Dec 2016 17:28:28 GMT 
send: 'GET /action/cookieAbsent HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: journals.sagepub.com\r\nConnection: close\r\nUser-Agent: Python-urllib/2.7\r\n\r\n' 
reply: 'HTTP/1.1 200 OK\r\n' 
header: Server: AtyponWS/7.1 
header: Cache-Control: no-cache 
header: Pragma: no-cache 
header: X-Webstats-RespID: 8344872279f77f45555d5f9aeb97985b 
header: Set-Cookie: JSESSIONID=aaavQMGH8mvlh_-5Ct7Jv; path=/ 
header: Content-Type: text/html; charset=UTF-8 
header: Connection: close 
header: Transfer-Encoding: chunked 
header: Date: Wed, 14 Dec 2016 17:28:28 GMT 
header: Vary: Accept-Encoding 

Répondre

2

Je parie que c'est un problème avec l'en-tête User Agent (je viens d'utiliser curl http://journals.sagepub.com/doi/pdf/10.1177/0956797614553009 et a obtenu le même que vous signalez avec urllib2). Cela fait partie de l'en-tête de la demande qui permet à un site Web de savoir quel type de programme/utilisateur/tout ce qui accède au site (pas la bibliothèque, la requête HTTP).

By default, it looks like urllib2 uses:Python-urllib/2.1
And requests uses:python-requests/{package version} {runtime}/{runtime version} {uname}/{uname -r}

Si vous travaillez sur un Mac, je parierai que le site est en train de lire Darwin/13.1.0 ou similaire et vous servir le macos contenu approprié. Sinon, il essaie probablement de vous diriger vers un autre contenu par défaut (ou vous empêche d'extraire cette URL).

+0

Vous êtes sur la bonne voie - J'ai réussi à faire fonctionner la version d'urllib2 en ajustant les en-têtes. Il ne s'agissait pas d'un agent utilisateur, mais d'un cookie manquant. Je vais éditer ma question, parce que maintenant je suis curieux d'où vient le cookie. – nrlakin

+0

Cela provient probablement d'un en-tête 'redirect': http://www.diveintopython.net/http_web_services/redirects.html – cwallenpoole

+0

C'était tout. La version 302 d'urllib2 avec un en-tête Set-Cookie, puis renvoie une page d'erreur pour "No Cookie Set". – nrlakin