Błąd HTTP 403 w Python 3 Web Scraping

103

Próbowałem złomować witrynę internetową w celach praktycznych, ale nadal otrzymywałem błąd HTTP 403 (czy uważa, że ​​jestem botem)?

Oto mój kod:

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

Pojawia się błąd:

 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
źródło

Odpowiedzi:

220

Dzieje się tak prawdopodobnie z powodu mod_securitylub podobnej funkcji bezpieczeństwa serwera, która blokuje znanych agentów użytkownika pająków / botów ( urllibużywa czegoś podobnego python urllib/3.3.0do łatwego wykrywania). Spróbuj ustawić znanego klienta użytkownika przeglądarki z:

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

To działa dla mnie.

Nawiasem mówiąc, w kodzie brakuje znaku „ ()after” .readw urlopenwierszu, ale myślę, że to literówka.

WSKAZÓWKA: ponieważ jest to ćwiczenie, wybierz inną, nieograniczoną stronę. Może urllibz jakiegoś powodu się blokują ...

Stefano Sanfilippo
źródło
Zakładam, że ponowne użycie reqdo wielu urlopenpołączeń jest bezpieczne .
Acumenus
Może być trochę za późno, ale mam już User-Agent w swoim kodzie, wciąż mi to dajeError 404: Access denied
Reema Parakh
To działa, ale czuję, że muszą mieć dobry powód, aby blokować boty, a ja
naruszam
39

Zdecydowanie blokuje, ponieważ używasz urllib opartego na kliencie użytkownika. To samo dzieje się ze mną w przypadku OfferUp. Możesz utworzyć nową klasę o nazwie AppURLopener, która nadpisuje klienta użytkownika w Mozilli.

import urllib.request

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

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

Źródło

zeta
źródło
2
Najlepsza odpowiedź nie zadziałała dla mnie, podczas gdy twoja. Wielkie dzięki!
Tarun Uday
Działa to dobrze, ale muszę dołączyć do tego konfigurację ssl. Jak mam to zrobic? Wcześniej dodałem go jako drugi parametr (urlopen (request, context = ctx))
Hauke
2
wygląda na to, że się otworzył, ale wyświetla komunikat „ValueError: read of closed file”
Martian2049
@zeta Jak udało Ci się zeskrobać OfferUp i podać wymagane współrzędne geograficzne, aby przeprowadzić wyszukiwanie ze skryptu?
CJ Travis
@CJTravis, nie skrobałem OfferUp. Właśnie pobierałem wartości pozycji na podstawie dokładnego adresu URL przedmiotu. To nie wymagało dla mnie żadnych współrzędnych geograficznych
zeta
14

„Jest to prawdopodobnie spowodowane mod_security lub podobną funkcją bezpieczeństwa serwera, która blokuje znane

pająk / bot

programy użytkownika (urllib używa czegoś takiego jak python urllib / 3.3.0, jest łatwo wykrywalny) ”- jak już wspomniał 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')

Web_byte jest obiektem bajt zwrócony przez serwer i zawartości typu obecnej w internetowej jest głównie UTF-8 . Dlatego musisz zdekodować bajt_web za pomocą metody dekodowania.

To rozwiązuje cały problem, gdy próbowałem usunąć ze strony internetowej za pomocą PyCharm

PS -> używam pythona 3.4

royatirek
źródło
3

Na podstawie poprzedniej odpowiedzi

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

To zadziałało dla mnie, wydłużając limit czasu.

VICTOR IWUOHA
źródło
2

Ponieważ strona działa w przeglądarce, a nie podczas wywoływania w programie w języku Python, wydaje się, że aplikacja internetowa obsługująca ten adres URL rozpoznaje, że żądasz treści, a nie przeglądarka.

Demonstracja:

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>

a treść w r.txt ma wiersz statusu:

HTTP/1.1 403 Forbidden

Spróbuj opublikować nagłówek „User-Agent”, który podszywa się pod klienta internetowego.

UWAGA: Strona zawiera wywołanie Ajax, które tworzy tabelę, którą prawdopodobnie chcesz przeanalizować. Będziesz musiał sprawdzić logikę javascript na stronie lub po prostu użyć debugera przeglądarki (takiego jak karta Firebug / Net), aby zobaczyć, który adres URL musisz wywołać, aby uzyskać zawartość tabeli.

Robert Lujo
źródło
1

Możesz spróbować na dwa sposoby. Szczegóły w tym linku .

1) Przez pip

pip install - uaktualnij certifi

2) Jeśli to nie zadziała, spróbuj uruchomić Cerificates.command, który jest dostarczany w pakiecie z Pythonem 3. * dla komputerów Mac: (Przejdź do lokalizacji instalacji Pythona i kliknij dwukrotnie plik)

open / Applications / Python \ 3. * / Install \ Certificates.command

Johnson
źródło
1

Jeśli czujesz się winny z powodu udawania klienta użytkownika jako Mozilli (komentarz w pierwszej odpowiedzi od Stefano), może to działać również z agentem użytkownika innym niż urllib. To działało w przypadku witryn, do których się odwołuję:

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

Moja aplikacja służy do testowania ważności poprzez skrobanie określonych linków, do których się odwołuję, w moich artykułach. Nie jest to zwykły skrobak.

Sudeep Prasad
źródło
1

W oparciu o poprzednie odpowiedzi zadziałało to dla mnie z Pythonem 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)
Jonny_P
źródło