HTTP-Fehler 403 in Python 3 Web Scraping

100

Ich habe versucht, eine Website zum Üben zu verschrotten, aber ich habe immer wieder den HTTP-Fehler 403 erhalten (glaubt ich, ich bin ein Bot)?

Hier ist mein Code:

#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 = []

Der Fehler, den ich bekomme, ist:

 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
Josh
quelle

Antworten:

203

Dies liegt wahrscheinlich an mod_securityoder einer ähnlichen Serversicherheitsfunktion, die bekannte Spider / Bot-Benutzeragenten blockiert ( urllibverwendet so etwas wie python urllib/3.3.0, es ist leicht zu erkennen). Versuchen Sie, einen bekannten Browser-Benutzeragenten einzurichten mit:

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

Das funktioniert bei mir.

Übrigens fehlt in Ihrem Code das ()Nachher .readin der urlopenZeile, aber ich denke, dass es ein Tippfehler ist.

TIPP: Da dies eine Übung ist, wählen Sie eine andere, nicht einschränkende Site. Vielleicht blockieren sie urllibaus irgendeinem Grund ...

Stefano Sanfilippo
quelle
Ich gehe davon aus, dass die Wiederverwendung reqfür mehrere urlopenAnrufe sicher ist .
Acumenus
Es mag etwas spät sein, aber ich habe bereits User-Agent in meinem Code, trotzdem gibt es mirError 404: Access denied
Reema Parakh
Dies funktioniert, aber ich denke, sie müssen einen guten Grund haben, Bots zu blockieren, und ich verstoße gegen ihre Nutzungsbedingungen
xjcl
39

Auf jeden Fall blockiert es aufgrund Ihrer Verwendung von urllib basierend auf dem Benutzeragenten. Das gleiche passiert mir mit OfferUp. Sie können eine neue Klasse namens AppURLopener erstellen, die den Benutzeragenten mit Mozilla überschreibt.

import urllib.request

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

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

Quelle

Zeta
quelle
2
Die beste Antwort hat bei mir nicht funktioniert, bei Ihnen nicht. Vielen Dank!
Tarun Uday
Dies funktioniert gut, aber ich muss die SSL-Konfiguration daran anhängen. Wie mache ich das? Bevor ich es gerade als zweiten Parameter hinzugefügt habe (urlopen (Anfrage, Kontext = ctx))
Hauke
2
Es sieht so aus, als ob es geöffnet wurde, aber es heißt 'ValueError: Lesen der geschlossenen Datei'
Martian2049
@zeta Wie haben Sie es geschafft, OfferUp zu kratzen und die erforderlichen Geokoordinaten für die Suche in einem Skript bereitzustellen?
CJ Travis
@ CJTravis, ich habe OfferUp nicht abgekratzt. Ich habe gerade Artikelwerte basierend auf einer genauen URL eines Artikels abgerufen. Das erforderte keine Geokoordinaten für mich
Zeta
13

"Dies liegt wahrscheinlich an mod_security oder einer ähnlichen Server-Sicherheitsfunktion, die bekannte Blöcke blockiert

Spinne / Bot

Benutzeragenten (urllib verwendet so etwas wie Python urllib / 3.3.0, es ist leicht zu erkennen) "- wie bereits von Stefano Sanfilippo erwähnt

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

Das web_byte ist ein vom Server zurückgegebenes Byte-Objekt, und der auf der Webseite vorhandene Inhaltstyp ist meistens utf-8 . Daher müssen Sie web_byte mithilfe der Decodierungsmethode dekodieren.

Dies löst das komplette Problem, während ich versucht habe, mit PyCharm von einer Website zu verschrotten

PS -> Ich benutze Python 3.4

Royatirek
quelle
1

Da die Seite im Browser funktioniert und nicht beim Aufrufen innerhalb des Python-Programms, scheint die Web-App, die diese URL bereitstellt, zu erkennen, dass Sie den Inhalt nicht vom Browser anfordern.

Demonstration:

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>

und der Inhalt in r.txt hat Statuszeile:

HTTP/1.1 403 Forbidden

Versuchen Sie, den Header 'User-Agent' zu veröffentlichen, der den Webclient fälscht .

HINWEIS: Die Seite enthält einen Ajax-Aufruf, der die Tabelle erstellt, die Sie wahrscheinlich analysieren möchten. Sie müssen die Javascript-Logik der Seite überprüfen oder einfach den Browser-Debugger (wie die Registerkarte Firebug / Net) verwenden, um festzustellen, welche URL Sie aufrufen müssen, um den Inhalt der Tabelle abzurufen.

Robert Lujo
quelle
1

Sie können es auf zwei Arten versuchen. Das Detail finden Sie in diesem Link .

1) Über Pip

pip install - Upgrade-Zertifikat

2) Wenn es nicht funktioniert, versuchen Sie, einen Cerificates.command auszuführen, der im Lieferumfang von Python 3 enthalten ist. * Für Mac: (Gehen Sie zu Ihrem Python-Installationsort und doppelklicken Sie auf die Datei.)

Öffnen Sie / Applications / Python \ 3. * / Install \ Certificates.command

Johnson
quelle
1

Basierend auf der vorherigen Antwort,

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

Dies funktionierte für mich, indem das Timeout verlängert wurde.

VICTOR IWUOHA
quelle
0

Wenn Sie sich schuldig fühlen, den User-Agent als Mozilla vorgetäuscht zu haben (Kommentar in der Top-Antwort von Stefano), könnte dies auch mit einem Nicht-Urllib-User-Agent funktionieren. Dies funktionierte für die Websites, auf die ich verweise:

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

Meine Anwendung besteht darin, die Gültigkeit zu testen, indem bestimmte Links, auf die ich in meinen Artikeln verweise, entfernt werden. Kein generischer Schaber.

Sudeep Prasad
quelle
0

Basierend auf früheren Antworten hat dies bei mir mit Python 3.7 funktioniert

from urllib.request import Request, urlopen

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

print(webpage)
Jonny_P
quelle