Errore HTTP 403 in Python 3 Web Scraping


100

Stavo cercando di eliminare un sito Web per esercitarmi, ma ho continuato a ricevere l'errore HTTP 403 (pensa che io sia un bot)?

Ecco il mio codice:

#import requests
import urllib.request
from bs4 import BeautifulSoup
#from urllib import urlopen
import re

webpage = urllib.request.urlopen('http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1').read
findrows = re.compile('<tr class="- banding(?:On|Off)>(.*?)</tr>')
findlink = re.compile('<a href =">(.*)</a>')

row_array = re.findall(findrows, webpage)
links = re.finall(findlink, webpate)

print(len(row_array))

iterator = []

L'errore che ottengo è:

 File "C:\Python33\lib\urllib\request.py", line 160, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python33\lib\urllib\request.py", line 479, in open
    response = meth(req, response)
  File "C:\Python33\lib\urllib\request.py", line 591, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python33\lib\urllib\request.py", line 517, in error
    return self._call_chain(*args)
  File "C:\Python33\lib\urllib\request.py", line 451, in _call_chain
    result = func(*args)
  File "C:\Python33\lib\urllib\request.py", line 599, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

Risposte:


206

Ciò è probabilmente dovuto mod_securityo qualche caratteristica di sicurezza del server simile che blocca gli agenti utente spider / bot conosciuti ( urllibusa qualcosa di simile python urllib/3.3.0, è facilmente rilevabile). Prova a impostare un agente utente del browser noto con:

from urllib.request import Request, urlopen

req = Request('http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1', headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()

Questo funziona per me.

A proposito, nel tuo codice manca il ()dopo .readnella urlopenriga, ma penso che sia un errore di battitura.

SUGGERIMENTO: poiché questo è un esercizio, scegli un sito diverso e non restrittivo. Forse stanno bloccando urllibper qualche motivo ...


Presumo sia sicuro da riutilizzare reqper più urlopenchiamate.
Acumenus

Potrebbe essere un po 'tardi, ma ho già User-Agent nel mio codice, ancora mi dàError 404: Access denied
Reema Parakh

Funziona, ma sento che devono avere una buona ragione per bloccare i bot e sto violando i loro termini di servizio
xjcl

39

Sicuramente si blocca a causa del tuo utilizzo di urllib basato sull'agente utente. Questa stessa cosa sta accadendo a me con OfferUp. Puoi creare una nuova classe chiamata AppURLopener che sostituisce lo user-agent con Mozilla.

import urllib.request

class AppURLopener(urllib.request.FancyURLopener):
    version = "Mozilla/5.0"

opener = AppURLopener()
response = opener.open('http://httpbin.org/user-agent')

fonte


2
La risposta migliore non ha funzionato per me, mentre la tua sì. Molte grazie!
Tarun Uday

Funziona benissimo, ma devo allegare la configurazione SSL a questo. Come faccio a fare questo? Prima di aggiungerlo come secondo parametro (urlopen (request, context = ctx))
Hauke

2
sembra che sia stato aperto ma dice "ValueError: read of closed file"
Martian2049

@zeta Come sei riuscito a racimolare OfferUp e fornire le coordinate geografiche necessarie per eseguire la ricerca da uno script?
CJ Travis

@ CJTravis, non stavo raschiando OfferUp. Stavo solo recuperando i valori degli elementi in base a un URL esatto di un elemento. Per me non sono necessarie coordinate geografiche
zeta

13

"Questo è probabilmente a causa di mod_security o di qualche caratteristica di sicurezza del server simile che blocca noti

ragno / bot

agenti utente (urllib usa qualcosa come python urllib / 3.3.0, è facilmente rilevabile) "- come già menzionato da Stefano Sanfilippo

from urllib.request import Request, urlopen
url="https://stackoverflow.com/search?q=html+error+403"
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})

web_byte = urlopen(req).read()

webpage = web_byte.decode('utf-8')

Il web_byte è un oggetto byte restituito dal server e il tipo di contenuto presente nella pagina web è principalmente utf-8 . Pertanto è necessario decodificare web_byte utilizzando il metodo di decodifica.

Questo risolve il problema completo mentre stavo cercando di eliminare da un sito Web utilizzando PyCharm

PS -> Uso python 3.4


1

Poiché la pagina funziona nel browser e non durante la chiamata all'interno del programma python, sembra che l'app Web che serve quell'URL riconosca che richiedi il contenuto non dal browser.

Dimostrazione:

curl --dump-header r.txt http://www.cmegroup.com/trading/products/#sortField=oi&sortAsc=false&venues=3&page=1&cleared=1&group=1

...
<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
You don't have permission to access ...
</HTML>

e il contenuto in r.txt ha una riga di stato:

HTTP/1.1 403 Forbidden

Prova a pubblicare l'intestazione "User-Agent" che falsifica il client web.

NOTA: la pagina contiene una chiamata Ajax che crea la tabella che probabilmente desideri analizzare. Dovrai controllare la logica javascript della pagina o semplicemente usare il debugger del browser (come la scheda Firebug / Net) per vedere quale URL devi chiamare per ottenere il contenuto della tabella.


1

Puoi provare in due modi. Il dettaglio è in questo link .

1) Via pip

pip install - aggiorna certifi

2) Se non funziona, prova a eseguire un Cerificates.command fornito in bundle con Python 3. * per Mac: (vai alla posizione di installazione di Python e fai doppio clic sul file)

apri / Applicazioni / Python \ 3. * / Install \ Certificates.command


1

Sulla base della risposta precedente,

from urllib.request import Request, urlopen       
#specify url
url = 'https://xyz/xyz'
req = Request(url, headers={'User-Agent': 'XYZ/3.0'})
response = urlopen(req, timeout=20).read()

Questo ha funzionato per me estendendo il timeout.


0

Se ti senti in colpa per aver simulato lo user-agent come Mozilla (commento nella risposta in alto di Stefano), potrebbe funzionare anche con uno User-Agent non urllib. Ha funzionato per i siti a cui faccio riferimento:

    req = urlrequest.Request(link, headers={'User-Agent': 'XYZ/3.0'})
    urlrequest.urlopen(req, timeout=10).read()

La mia domanda è di testare la validità raschiando link specifici a cui mi riferisco, nei miei articoli. Non un generico raschietto.


0

Sulla base delle risposte precedenti, questo ha funzionato per me con Python 3.7

from urllib.request import Request, urlopen

req = Request('Url_Link', headers={'User-Agent': 'XYZ/3.0'})
webpage = urlopen(req, timeout=10).read()

print(webpage)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.