2013-02-13 10 views
15

C'è un file FLV sul Web che può essere scaricato direttamente in Chrome. Il file è un programma televisivo, pubblicato da CCTV (China Central Television). CCTV è un'emittente pubblica senza scopo di lucro, finanziata dal contribuente cinese, che ci consente di scaricare i loro contenuti senza violare i diritti d'autore.Emulazione di un browser per scaricare un file?

Utilizzando wget, posso scaricare il file da un indirizzo diverso, ma non dall'indirizzo che funziona in Chrome.

Questo è quello che ho cercato di fare:

url='http://114.80.235.200/f4v/94/163005294.h264_1.f4v?10000&key=7b9b1155dc632cbab92027511adcb300401443020d&playtype=1&tk=163659644989925531390490125&brt=2&bc=0&nt=0&du=1496650&ispid=23&rc=200&inf=1&si=11000&npc=1606&pp=0&ul=2&mt=-1&sid=10000&au=0&pc=0&cip=222.73.44.31&hf=0&id=tudou&itemid=135558267&fi=163005294&sz=59138302' 

wget -c $url --user-agent="" -O xfgs.f4v 

Questo non funziona neanche:

wget -c $url -O xfgs.f4v 

l'output è:

Connecting to 118.26.57.12:80... connected. 
HTTP request sent, awaiting response... 403 Forbidden 
2013-02-13 09:50:42 ERROR 403: Forbidden. 

Che cosa sto facendo sbagliato?

Alla fine voglio scaricarlo con la libreria Python mechanize. Ecco il codice che sto usando per questo:

import mechanize 
br = mechanize.Browser() 
br = mechanize.Browser() 
br.set_handle_robots(False) 
br.set_handle_equiv(False) 
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')] 
url='http://114.80.235.200/f4v/94/163005294.h264_1.f4v?10000&key=7b9b1155dc632cbab92027511adcb300401443020d&playtype=1&tk=163659644989925531390490125&brt=2&bc=0&nt=0&du=1496650&ispid=23&rc=200&inf=1&si=11000&npc=1606&pp=0&ul=2&mt=-1&sid=10000&au=0&pc=0&cip=222.73.44.31&hf=0&id=tudou&itemid=135558267&fi=163005294&sz=59138302' 
r = br.open(url).read() 
tofile=open("/tmp/xfgs.f4v","w") 
tofile.write(r) 
tofile.close() 

Questo è il risultato:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/dist-packages/mechanize/_mechanize.py", line 203, in open 
    return self._mech_open(url, data, timeout=timeout) 
    File "/usr/lib/python2.7/dist-packages/mechanize/_mechanize.py", line 255, in _mech_open 
raise response 
mechanize._response.httperror_seek_wrapper: HTTP Error 403: Forbidden 

Qualcuno può spiegare come ottenere il codice di mechanize a lavorare per favore?

+1

Cosa succede se usa: 'user_agent = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv: 1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1)'' e poi ' wget -c "$ {url}" --user-agent = "$ {user_agent}" -O x fgs.f4v'? Se ciò non funziona, allora Python potrebbe non essere in grado di aiutarti! – Johnsyweb

+7

Il motivo per cui si ottiene una risposta 403 è molto probabile perché il sito Web mantiene uno stato quando lo si visita in un browser, molto probabilmente un cookie. Questo è ciò che YouTube fa. Esporta il tuo cookie dal browser e impostalo su wget (puoi semplicemente utilizzare l'intestazione "Cookie:") e dovrebbe funzionare. –

+0

@Johnsyweb Python può perfettamente emulare un browser nella maggior parte dei casi (beh, eccetto i siti dispari che impostano un cookie tramite JavaScript e così via). –

risposta

20

Prima di tutto, se si sta tentando qualsiasi tipo di raschiamento (sì, questo conta come raschiamento anche se non si sta necessariamente analizzando HTML), si dispone di una certa quantità di indagini preliminari da eseguire.

Se non si dispone già di Firefox e Firebug, ottenerli. Quindi se non hai già Chrome, prendilo.

Avvia Firefox/Firebug e Chrome, cancella tutti i cookie/ecc. Quindi apri Firebug e in Chrome apri View-> Developer-> Developer Tools.

Quindi caricare la pagina principale del video che si sta tentando di afferrare. Prendi nota di eventuali cookie/intestazioni/variabili POST/variabili stringa di query che vengono impostate al caricamento della pagina. Potresti voler salvare queste informazioni da qualche parte.

Quindi provare a scaricare il video, ancora una volta, prendere nota di eventuali cookie/intestazioni/variabili post/variabili stringa di query che vengono impostate quando viene caricato il video. È molto probabile che sia stato impostato un cookie o una variabile POST al momento del caricamento iniziale della pagina, necessario per estrarre effettivamente il file video.

Quando scrivi il tuo python, avrai bisogno di emulare questa interazione il più vicino possibile. Utilizzare python-requests. Questa è probabilmente la più semplice libreria di URL disponibile e, a meno che non ci si imbatti in un muro in qualche modo con esso (qualcosa che non può fare), non utilizzerei mai altro. Il secondo ho iniziato a utilizzare python-requests, tutto il mio codice di recupero URL ridotto di un fattore 5x.

Ora, probabilmente le cose non funzioneranno la prima volta che le provate. Soooo, dovrai caricare la pagina principale usando python. Stampa tutti i tuoi cookie/intestazioni/variabili POST/variabili stringa di query e confrontali con ciò che Chrome/Firebug ha avuto. Quindi prova a caricare il tuo video, ancora una volta, confronta tutti questi valori (ciò significa che TU hai inviato il server e ciò che il SERVER ti ha inviato anche tu). Avrai bisogno di capire cosa c'è di diverso tra loro (non ti preoccupare, TUTTI abbiamo imparato questo nella scuola materna ... "una di queste cose non è come l'altra") e analizziamo come questa differenza stia rompendo le cose.

Se alla fine non riesci ancora a capirlo, probabilmente devi guardare il codice HTML della pagina che contiene il link al film. Cerca qualsiasi javascript nella pagina. Quindi usa Firebug/Chrome Developer Tools per ispezionare il javascript e vedere se sta facendo un qualche tipo di gestione della sessione utente.Se genera in qualche modo token (cookie o variabili POST/GET) relativi all'accesso video, è necessario emulare il suo metodo di tokenizzazione in python.

Speriamo che tutto ciò sia utile e non sembri troppo spaventoso. La chiave è che avrai bisogno di essere uno scienziato. Scopri cosa sai, cosa non fai, cosa vuoi e inizia a sperimentare e registrare i risultati. Alla fine emergerà un modello.

Edit: di chiarire le fasi

  1. indagare come stato viene mantenuto
  2. Tirare pagina iniziale con pitone, afferrare qualsiasi informazioni di stato è necessario da esso
  3. Eseguire una creazione di token che può essere richiesto con informazioni di stato
  4. Estrarre il video utilizzando i token dai passaggi 2 e 3
  5. Se la situazione scoppia, emettere la richiesta/risposta ders, biscotti, interrogazione Vars, Vars postali, e confrontarle con Chrome/Firebug
  6. Ritorna al punto 1. fino a trovare una soluzione

Edit: Si può anche essere reindirizzato a uno dei due di queste richieste (la pagina html o il download del file). Molto probabilmente mancherà la richiesta/risposta in Firebug/Chrome se ciò accade. La soluzione sarebbe quella di utilizzare uno sniffer come LiveHTTPHeaders, o come è stato suggerito da altri risponditori, WireShark o Fiddler. Nota che Fiddler non ti farà bene se sei su una macchina Linux o OSX. È solo per Windows ed è decisamente focalizzato sullo sviluppo .NET ... (ugh). Wireshark è molto utile ma eccessivo per la maggior parte dei problemi e, a seconda del computer in uso, si potrebbero avere problemi a farlo funzionare. Quindi suggerirei LiveHTTPHeaders.

mi piace questo tipo di problema

+5

onestamente mi piacciono queste risposte, suona come la metafora di "non darmi pesce ma impara a pescare". E questi sono buoni suggerimenti. –

+0

Bene, questa è la programmazione giusta? :) grazie, il modo migliore per imparare è facendo (debugging). Rompi le cose e scopri perché hanno rotto. Quindi capisci meglio l'intero sistema, piuttosto che affrontare una soluzione specifica per il dominio-dominio –

+0

Per automatizzare il web, ho spesso usato questi tre strumenti: - Strumenti per sviluppatori di Chrome con abilita l'opzione 'Conserva registro' per la rete e Console - Quando vengono identificate le richieste POST/GET (avete bisogno di alcune competenze per questo), io uso 'Copia come arricciato' - Quindi scrivo il mio python per automatizzare il caso, ho trovato anche questo strumento: http: // curl .trillworks.com/# python che genera codice per me. Potrebbe anche essere necessario utilizzare cookiejar di python/urllib2 per mantenere i cookie Puoi anche usare nodejs o phantomjs per eseguire/evalare facilmente i codici Javascript, all'interno del tuo codice – hzrari

5

Sembra che mechanize possa fare una navigazione di stato, il che significa che manterrà il contesto e i cookie tra le richieste del browser. Vorrei suggerire di caricare prima la pagina completa in cui si trova il video, quindi fare un secondo tentativo per scaricare il video esplicitamente. In questo modo, il server web penserà che si tratta di un completo (legit) sessione di navigazione in corso

0
from urllib import urlopen 
print urlopen(url) #python built-in high level interface to get ANY online resources, auto responds to HTTP error codes. 
+0

no amico non è una soluzione reale IMHO – 0x90

4

Per chiarire la parte "perché" della domanda è possibile instradare il browser e le richieste del codice tramite un proxy di debug. Se stai usando Windows suggerisco fiddler2. Esistono altri proxy di debug per altre piattaforme. Ma Fiddler2 è sicuramente il mio preferito.

http://www.fiddler2.com/fiddler2/

https://www.owasp.org/index.php/Category:OWASP_WebScarab_Project

http://www.charlesproxy.com/

O più basso livello http://netcat.sourceforge.net/

http://www.wireshark.org/

Una volta che sai le differenze di solito è molto più semplice di trovare una soluzione .Ho il sospetto che le altre risposte riguardo alla navigazione di stato/ai cookie siano corrette. Con gli strumenti menzionati è possibile analizzare questi cookie e creare una soluzione adeguata senza l'automazione del browser.

+0

+1 per semplicità – flup

2

C'è un open source, libreria Python, chiamato ghost, che avvolge un senza testa, il browser WebKit, in modo da poter controllare tutto attraverso una semplice API:

from ghost import Ghost 
ghost = Ghost() 

page, resources = ghost.open('http://my.web.page') 

Esso supporta i cookie, JavaScript e tutto il resto. È possibile inserire JavaScript nella pagina, e mentre è senza testa, quindi non esegue il rendering di alcun elemento grafico, hai ancora il DOM. È un browser completo.

Non sarebbe scalabile, ma è molto divertente e potrebbe essere utile quando hai bisogno di qualcosa che si avvicina a un browser completo.

+1

Questo è probabilmente eccessivo per il suo problema, dal momento che carica su un'istanza completa WebKit/JavascriptCore o V8. Ciò rende Python non-puro e le dipendenze possono diventare un problema a seconda di dove viene eseguito il suo codice. Ma indipendentemente dai fantastici suggerimenti! Non l'avevo mai visto prima. –

3

Penso che molti siti utilizzino collegamenti temporanei che esistono solo nella sessione. Il codice nell'url è probabilmente qualcosa come il tuo id di sessione. Ciò significa che il collegamento particolare non funzionerà mai più.

Dovrai riaprire la pagina che contiene il collegamento utilizzando una libreria che supporta questa sessione (come menzionato in altre risposte). E quindi provare a individuare il collegamento e usarlo solo in questa sessione.

5

Supponendo di non aver digitato manualmente l'URL dal blu, utilizzare mechanize per andare prima alla pagina da cui l'hai ottenuto. Quindi emula l'azione eseguita per scaricare il file effettivo (probabilmente facendo clic su un collegamento o un pulsante).

Questo potrebbe non funzionare anche se Mechanize mantiene lo stato di cookie e reindirizzamenti, ma non gestisce alcuna modifica in tempo reale JavaScript alle pagine html. Per verificare se JavaScript è fondamentale per l'operazione, passa da JavaScript a Chrome (o qualsiasi altro browser) e assicurati di poter scaricare il file. Se è necessario JavaScript, proverei a guidare a livello di codice un browser per ottenere il file.

Il mio approccio al solito di provare questo tipo di raschiatura è

  1. provare wget o pitoni urllib2
  2. provare meccanizzare
  3. auto un browser

A meno che non v'è una certa captcha, l'ultima uno di solito funziona, ma gli altri sono più facili (e più veloci).

0

Hai provato a richiedere il modulo? è molto più semplice da usare rispetto a urllib2 e pycurl ecc. ma è potente.Ha seguenti caratteristiche: Il collegamento è here

  • Domains International e gli URL
  • Keep-Alive & Connection Pooling
  • sessioni con Cookie Persistenza
  • Browser stile di verifica SSL
  • di base/autenticazione Digest
  • Elegant Key/Value Cookies
  • Decompressione automatica
  • Bodies Unicode risposta
  • caricamento di file a più parti
  • Connection Timeout
  • .netrc supporta
  • Python 2,6-3,3
  • thread-safe.
  • 0

    Si potrebbe utilizzare Internet Download Manager è in grado di catturare e scaricare qualsiasi supporto in streaming da qualsiasi sito web

    2

    Mentre l'attuale risposta accettata (di G. Shearer) è la migliore possibile consigli per raschiare in generale, ho trovato un modo per saltare alcuni passi - con a firefox extension called cliget che prende il contesto della richiesta con tutte le intestazioni HTTP e cookie e genera un comando curl (o wget) che viene copiato negli appunti.

    EDIT: questa funzione è disponibile nei pannelli di rete di Firebug e il debugger di cromo anche - tasto destro del mouse richiesta, "Copia come ricciolo"

    maggior parte delle volte si otterrà un comando molto dettagliato con alcune intestazioni apparentemente non necessarie, ma è possibile rimuoverle una alla volta fino a quando il server rifiuta la richiesta, invece del contrario (che, onestamente, trovo frustrante - spesso mi sono bloccato pensando a quale intestazione mancava nella richiesta).

    (Inoltre, si potrebbe desiderare di rimuovere l'opzione -O dal curl riga di comando per vedere il risultato in stdout invece di scaricare in un file, e aggiungere -v per visualizzare l'elenco intestazione completa)

    Anche se si non voglio usare curl/wget, convertire una linea di comando curl/wget in codice python è solo questione di sapere come aggiungere le intestazioni a una richiesta urllib (o qualsiasi altra libreria di richieste http)