【问题标题】:urllib2.HTTPError: HTTP Error 403: Forbiddenurllib2.HTTPError:HTTP 错误 403:禁止
【发布时间】:2012-10-29 11:59:58
【问题描述】:

我正在尝试使用 python 自动下载历史股票数据。我尝试打开的 URL 以 CSV 文件响应,但我无法使用 urllib2 打开。我曾尝试按照前面几个问题中的说明更改用户代理,我什至尝试接受响应 cookie,但没有成功。你能帮忙吗?

注意:同样的方法适用于 yahoo Finance。

代码:

import urllib2,cookielib

site= "http://www.nseindia.com/live_market/dynaContent/live_watch/get_quote/getHistoricalData.jsp?symbol=JPASSOCIAT&fromDate=1-JAN-2012&toDate=1-AUG-2012&datePeriod=unselected&hiddDwnld=true"

hdr = {'User-Agent':'Mozilla/5.0'}

req = urllib2.Request(site,headers=hdr)

page = urllib2.urlopen(req)

错误

文件“C:\Python27\lib\urllib2.py”,第 527 行,在 http_error_default 中 raise HTTPError(req.get_full_url(), code, msg, hdrs, fp) urllib2.HTTPError: HTTP Error 403: Forbidden

感谢您的帮助

【问题讨论】:

  • 你是用windows做平台的吗?

标签: python http urllib


【解决方案1】:

值得尝试的一件事就是更新 python 版本。几个月前,我的一个爬虫脚本停止在 Windows 10 上使用 403。任何 user_agents 都没有帮助,我正要放弃脚本。今天,我在 Ubuntu 上使用 Python(3.8.5 - 64 位)尝试了相同的脚本,并且没有错误。 Windows 的 python 版本有点旧,如 3.6.2 - 32 位。将 Windows 10 上的 python 升级到 3.9.5 - 64 位后,我不再看到 403。如果你试一试,别忘了运行“pip freeze > requirements.txt”来导出包条目。我当然忘记了。 当 403 将来再次出现时,这篇文章也是对我的提醒。

【讨论】:

    【解决方案2】:

    当您请求的服务器不知道请求来自哪里时,通常会发生此错误,服务器这样做是为了避免任何不必要的访问。您可以通过定义一个标头并将其沿 urllib.request 传递来绕过此错误

    这里的代码:

    #defining header
    header= {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) ' 
          'AppleWebKit/537.11 (KHTML, like Gecko) '
          'Chrome/23.0.1271.64 Safari/537.11',
          'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
          'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
          'Accept-Encoding': 'none',
          'Accept-Language': 'en-US,en;q=0.8',
          'Connection': 'keep-alive'}
    
    #the URL where you are requesting at
    req = urllib.request.Request(url=your_url, headers=header) 
    page = urllib.request.urlopen(req).read()
    

    【讨论】:

      【解决方案3】:
      import urllib.request
      
      bank_pdf_list = ["https://www.hdfcbank.com/content/bbp/repositories/723fb80a-2dde-42a3-9793-7ae1be57c87f/?path=/Personal/Home/content/rates.pdf",
      "https://www.yesbank.in/pdf/forexcardratesenglish_pdf",
      "https://www.sbi.co.in/documents/16012/1400784/FOREX_CARD_RATES.pdf"]
      
      
      def get_pdf(url):
          user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'
          
          #url = "https://www.yesbank.in/pdf/forexcardratesenglish_pdf"
          headers={'User-Agent':user_agent,} 
          
          request=urllib.request.Request(url,None,headers) #The assembled request
          response = urllib.request.urlopen(request)
          #print(response.text)
          data = response.read()
      #    print(type(data))
          
          name = url.split("www.")[-1].split("//")[-1].split(".")[0]+"_FOREX_CARD_RATES.pdf"
          f = open(name, 'wb')
          f.write(data)
          f.close()
          
      
      for bank_url in bank_pdf_list:
          try: 
              get_pdf(bank_url)
          except:
              pass
      

      【讨论】:

        【解决方案4】:

        NSE 网站已更改,旧脚本对当前网站来说是半最佳的。这个 sn-p 可以收集日常的安全细节。详细信息包括代码、证券类型、前一收盘价、开盘价、最高价、最低价、平均价格、交易量、成交量、交易数量、交付数量以及交付与交易的百分比。这些以字典形式的列表方便地呈现。

        带有请求和 BeautifulSoup 的 Python 3.X 版本

        from requests import get
        from csv import DictReader
        from bs4 import BeautifulSoup as Soup
        from datetime import date
        from io import StringIO 
        
        SECURITY_NAME="3MINDIA" # Change this to get quote for another stock
        START_DATE= date(2017, 1, 1) # Start date of stock quote data DD-MM-YYYY
        END_DATE= date(2017, 9, 14)  # End date of stock quote data DD-MM-YYYY
        
        
        BASE_URL = "https://www.nseindia.com/products/dynaContent/common/productsSymbolMapping.jsp?symbol={security}&segmentLink=3&symbolCount=1&series=ALL&dateRange=+&fromDate={start_date}&toDate={end_date}&dataType=PRICEVOLUMEDELIVERABLE"
        
        
        
        
        def getquote(symbol, start, end):
            start = start.strftime("%-d-%-m-%Y")
            end = end.strftime("%-d-%-m-%Y")
        
            hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
                 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                 'Referer': 'https://cssspritegenerator.com',
                 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
                 'Accept-Encoding': 'none',
                 'Accept-Language': 'en-US,en;q=0.8',
                 'Connection': 'keep-alive'}
        
            url = BASE_URL.format(security=symbol, start_date=start, end_date=end)
            d = get(url, headers=hdr)
            soup = Soup(d.content, 'html.parser')
            payload = soup.find('div', {'id': 'csvContentDiv'}).text.replace(':', '\n')
            csv = DictReader(StringIO(payload))
            for row in csv:
                print({k:v.strip() for k, v in row.items()})
        
        
         if __name__ == '__main__':
             getquote(SECURITY_NAME, START_DATE, END_DATE)
        

        此外,这是相对模块化的,可以使用 sn-p。

        【讨论】:

        • 谢谢,伙计!这对我有用,而不是来自@andrean 的上述答案
        • 嗨,我真的不知道该去哪里打我的头了,我已经尝试过这个解决方案等等,但我一直收到错误 403。还有什么我可以尝试的吗?
        • 403 状态是为了通知您的浏览器未通过身份验证以使用此服务。在您的情况下,它可能确实需要使用基本身份验证、oauth 等进行身份验证。
        【解决方案5】:

        这适用于 Python 3

        import urllib.request
        
        user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7'
        
        url = "http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers"
        headers={'User-Agent':user_agent,} 
        
        request=urllib.request.Request(url,None,headers) #The assembled request
        response = urllib.request.urlopen(request)
        data = response.read() # The data u need
        

        【讨论】:

        • 确实有些网站(包括维基百科)会阻止常见的非浏览器用户代理字符串,例如 Python 库发送的“Python-urllib/x.y”。即使是简单的“Mozilla”或“Opera”通常也足以绕过它。当然,这不适用于原始问题,但知道它仍然很有用。
        【解决方案6】:

        通过添加更多标题,我能够获取数据:

        import urllib2,cookielib
        
        site= "http://www.nseindia.com/live_market/dynaContent/live_watch/get_quote/getHistoricalData.jsp?symbol=JPASSOCIAT&fromDate=1-JAN-2012&toDate=1-AUG-2012&datePeriod=unselected&hiddDwnld=true"
        hdr = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
               'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
               'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
               'Accept-Encoding': 'none',
               'Accept-Language': 'en-US,en;q=0.8',
               'Connection': 'keep-alive'}
        
        req = urllib2.Request(site, headers=hdr)
        
        try:
            page = urllib2.urlopen(req)
        except urllib2.HTTPError, e:
            print e.fp.read()
        
        content = page.read()
        print content
        

        实际上,它只适用于这个额外的标题:

        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        

        【讨论】:

        • 您认为原始请求中缺少哪些标头?
        • wireshark 显示只发送了 User-Agent,以及 Connection: close, Host: www.nseindia.com, Accept-Encoding: identity
        • 不客气,我真正做的是在浏览器中检查了您脚本中的 url,当它在那里工作时,我只是复制了浏览器发送的所有请求标头,并添加了它们在这里,这就是解决方案。
        • @Mee 你看过下面的答案了吗?它是专门为 python 3 解决的,检查它是否适合你......
        • 尝试将其他标头(来自我的回答)也添加到请求中。服务器可能返回 403 的原因还有很多,请查看有关该主题的其他答案。至于目标,尤其是google是个硬汉,有点难抓取,他们已经实现了很多防止抓取的方法。
        猜你喜欢
        • 2012-10-14
        • 2023-03-12
        • 2013-12-30
        • 2021-06-02
        • 2021-11-22
        • 2022-01-18
        • 2020-06-17
        • 2016-06-20
        • 1970-01-01
        相关资源
        最近更新 更多