Erro HTTP 403 em Python 3 Web Scraping

100

Eu estava tentando descartar um site para praticar, mas continuei recebendo o erro HTTP 403 (ele acha que sou um bot)?

Aqui está o meu código:

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

O erro que recebo é:

 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
fonte

Respostas:

206

Provavelmente, isso se deve a mod_securityalgum recurso de segurança de servidor semelhante que bloqueia agentes de usuário spider / bot conhecidos ( urllibusa algo como python urllib/3.3.0, é facilmente detectado). Tente configurar um agente de usuário de navegador conhecido com:

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

Isso funciona para mim.

A propósito, no seu código está faltando o ()depois .readna urlopenlinha, mas acho que é um erro de digitação.

DICA: como este é um exercício, escolha um local diferente e não restritivo. Talvez eles estejam bloqueando urllibpor algum motivo ...

Stefano Sanfilippo
fonte
Presumo que seja seguro reutilizá-lo reqem várias urlopenchamadas.
Acumenus
Pode ser um pouco tarde, mas eu já tenho User-Agent em meu código, ainda me dáError 404: Access denied
Reema Parakh
Isso funciona, mas acho que eles devem ter um bom motivo para bloquear bots e estou violando seus termos de serviço
xjcl
39

Definitivamente, ele está bloqueando por causa do uso do urllib com base no agente do usuário. A mesma coisa está acontecendo comigo com OfferUp. Você pode criar uma nova classe chamada AppURLopener que substitui o agente do usuário pelo Mozilla.

import urllib.request

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

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

Fonte

zeta
fonte
2
A primeira resposta não funcionou para mim, enquanto a sua funcionou. Muito obrigado!
Tarun Uday
Isso funciona muito bem, mas preciso anexar a configuração SSL a isso. Como eu faço isso? Antes de adicioná-lo como um segundo parâmetro (urlopen (request, context = ctx))
Hauke,
2
parece que foi aberto, mas diz 'ValueError: leitura do arquivo fechado'
Martian2049
@zeta Como você conseguiu extrair OfferUp e fornecer as coordenadas geográficas necessárias para realizar a pesquisa em um script?
CJ Travis
@CJTravis, eu não estava rasgando OfferUp. Eu estava apenas recuperando valores de itens com base na URL exata de um item. Isso não exigiu nenhuma coordenada geográfica para mim
zeta
13

"Isso é provavelmente devido ao mod_security ou algum recurso de segurança de servidor semelhante que bloqueia

spider / bot

agentes de usuário (urllib usa algo como python urllib / 3.3.0, é facilmente detectado) "- como já mencionado por 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')

O web_byte é um objeto de byte retornado pelo servidor e o tipo de conteúdo presente na página da web é principalmente utf-8 . Portanto, você precisa decodificar o web_byte usando o método de decodificação.

Isso resolve o problema completo enquanto eu tentava fazer um scrap de um site usando PyCharm

PS -> Eu uso python 3.4

Royatirek
fonte
1

Uma vez que a página funciona no navegador e não ao chamar dentro do programa python, parece que o aplicativo da web que serve esse url reconhece que você não solicita o conteúdo pelo navegador.

Demonstração:

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 o conteúdo em r.txt tem linha de status:

HTTP/1.1 403 Forbidden

Tente postar o cabeçalho 'User-Agent' que falsifica o cliente da web.

NOTA: A página contém uma chamada Ajax que cria a tabela que você provavelmente deseja analisar. Você precisará verificar a lógica javascript da página ou simplesmente usar o depurador do navegador (como a guia Firebug / Net) para ver qual url você precisa chamar para obter o conteúdo da tabela.

Robert Lujo
fonte
1

Você pode tentar de duas maneiras. O detalhe está neste link .

1) Via pip

pip install - atualizar certifi

2) Se não funcionar, tente executar um Cerificates.command que vem junto com o Python 3. * para Mac: (Vá para o local de instalação do python e clique duas vezes no arquivo)

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

Johnson
fonte
1

Com base na resposta anterior,

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

Isso funcionou para mim estendendo o tempo limite.

VICTOR IWUOHA
fonte
0

Se você se sentir culpado por fingir que o user-agent é Mozilla (comentário na primeira resposta de Stefano), isso poderia funcionar com um User-Agent não urllib também. Isso funcionou para os sites que referi:

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

Minha aplicação é para testar a validade raspando links específicos aos quais me refiro, em meus artigos. Não é um raspador genérico.

Sudeep Prasad
fonte
0

Com base em respostas anteriores, isso funcionou para mim com 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)
Jonny_P
fonte