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

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


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


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


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.


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


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.


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.


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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.