Python 3 Web Scraping中的HTTP错误403


100

我试图通过抓取网站进行练习,但是我一直收到HTTP错误403(它认为我是机器人)吗?

这是我的代码:

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

我得到的错误是:

 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

Answers:


206

这可能是由于mod_security某种或类似的服务器安全功能阻止了已知的蜘蛛/机器人用户代理(urllib使用python urllib/3.3.0,很容易检测到)。尝试使用以下方法设置已知的浏览器用户代理:

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

这对我有用。

顺便说一句,在您的代码中您缺少该行中的()after ,但是我认为这是一个错字。.readurlopen

提示:由于这是练习,因此请选择其他非限制性站点。也许是urllib因为某种原因而被封锁...


我认为重复使用req多个urlopen电话是安全的。
Acumenus

可能Error 404: Access denied
为时

这行得通,但是我觉得他们必须有充分的理由阻止机器人,而且我违反了他们的服务条款
xjcl

39

肯定是因为您基于用户代理使用urllib而被阻止。OfferUp对我来说也是一样。您可以创建一个名为AppURLopener的新类,该类使用Mozilla覆盖用户代理。

import urllib.request

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

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

资源


2
最好的答案对我不起作用,而你的却对我有用。非常感谢!
塔伦·乌迪

这工作得很好,但我需要为此附加ssl配置。我该怎么做呢?在我将其添加为第二个参数(urlopen(request,context = ctx))之前
Hauke

2
看起来确实确实打开了,但它说“ ValueError:读取已关闭的文件”
Martian2049,2017年

@zeta您如何设法抓取OfferUp并提供必要的地理坐标以从脚本执行搜索?
CJ Travis

@CJTravis,我没有抓取OfferUp。我只是根据项目的确切URL检索项目值。我不需要任何地理坐标
zeta

13

“这可能是由于mod_security或某些类似的服务器安全功能阻止了已知的

蜘蛛/机器人

用户代理(urllib使用python urllib / 3.3.0之类的东西,很容易检测到)”-正如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是由服务器和类型存在于网页中的内容返回的字节对象主要是UTF-8 。因此,您需要使用解码方法来解码web_byte

当我尝试使用PyCharm从网站上抓取时,这解决了完整的问题

PS->我使用Python 3.4


1

由于该页面在浏览器中工作,而不是在python程序中调用时工作,因此似乎提供该URL的Web应用程序识别出您不是通过浏览器请求内容。

示范:

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>

并且r.txt中的内容具有状态行:

HTTP/1.1 403 Forbidden

尝试发布伪造网络客户端的标头“ User-Agent” 。

注意:该页面包含Ajax调用,该调用创建您可能要解析的表。您需要检查页面的javascript逻辑,或仅使用浏览器调试器(如Firebug / Net选项卡)查看需要调用哪个url才能获取表的内容。


1

您可以通过两种方式尝试。详细信息在此链接中

1)通过点

点安装-升级证书

2)如果它不起作用,请尝试运行适用于Mac的Python 3. *附带的Cerificates.command:(转到您的python安装位置,然后双击该文件)

打开/ Applications / Python \ 3。* / Install \ Certificates.command


1

根据先前的答案,

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

这通过延长超时为我工作。


0

如果您对将用户代理伪装成Mozilla感到内gui(在Stefano的最高答案中有评论),那么它也可以与非urllib User-Agent一起使用。这适用于我引用的网站:

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

我的应用程序是通过抓取我在文章中引用的特定链接来测试有效性。不是通用刮板。


0

根据先前的答案,这已在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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.