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

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ą ...


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


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


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.


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.


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


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.


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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.