urllib2.HTTPError: HTTP Error 403: Forbidden


104

ฉันกำลังพยายามดาวน์โหลดข้อมูลหุ้นในอดีตโดยอัตโนมัติโดยใช้ python URL ที่ฉันพยายามเปิดตอบกลับด้วยไฟล์ CSV แต่ฉันไม่สามารถเปิดโดยใช้ urllib2 ฉันได้ลองเปลี่ยนตัวแทนผู้ใช้ตามที่ระบุไว้ในคำถามสองสามข้อก่อนหน้านี้ฉันพยายามที่จะยอมรับคุกกี้ตอบกลับโดยที่โชคไม่ดี คุณสามารถช่วย.

หมายเหตุ: วิธีการเดียวกันนี้ใช้ได้กับ 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 เพิ่ม HTTPError (req.get_full_url (), code, msg, hdrs, fp) urllib2.HTTPError: HTTP Error 403: Forbidden

ขอบคุณสำหรับความช่วยเหลือ


คุณใช้ windows เป็นแพลตฟอร์มหรือไม่?
Denis

คำตอบ:


171

ด้วยการเพิ่มส่วนหัวอีกสองสามรายการฉันสามารถรับข้อมูลได้:

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',

ส่วนหัวใดต่อไปนี้ที่คุณคิดว่าขาดหายไปจากคำขอเริ่มต้น

1
Wirehark แสดงให้เห็นว่ามีการส่งเฉพาะ User-Agent พร้อมกับ Connection: close, Host: www.nseindia.com, Accept-Encoding: identity
andrean

1
คุณยินดีต้อนรับสิ่งที่ฉันทำจริงๆคือฉันตรวจสอบ url จากสคริปต์ของคุณในเบราว์เซอร์และเมื่อมันใช้งานได้ฉันก็แค่คัดลอกส่วนหัวของคำขอทั้งหมดที่เบราว์เซอร์ส่งมาและเพิ่มเข้าไปที่นี่และนั่นคือวิธีแก้ปัญหา
Andrean

1
@ มีคุณลองดูคำตอบด้านล่างนี้หรือไม่? ได้รับการแก้ไขโดยเฉพาะสำหรับ python 3 ตรวจสอบว่าเหมาะกับคุณหรือไม่ ...
Andrean

1
ลองเพิ่มส่วนหัวอื่น ๆ (จากคำตอบของฉัน) รวมทั้งคำขอ ยังคงมีสาเหตุอื่น ๆ อีกมากมายที่เซิร์ฟเวอร์อาจส่งคืน 403 โปรดดูคำตอบอื่น ๆ ในหัวข้อด้วย สำหรับเป้าหมายนั้น google เป็นสิ่งที่ยากและยากที่จะขูดพวกเขาได้ใช้วิธีการมากมายเพื่อป้องกันการขูด
Andrean

52

สิ่งนี้จะใช้ได้ใน 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

2
เป็นเรื่องจริงที่บางไซต์ (รวมถึง Wikipedia) บล็อกสตริงตัวแทนผู้ใช้ที่ไม่ใช่เบราว์เซอร์ทั่วไปเช่น "Python-urllib / xy" ที่ส่งโดยไลบรารีของ Python แม้แต่ "Mozilla" หรือ "Opera" ธรรมดาก็เพียงพอที่จะข้ามสิ่งนั้นได้ สิ่งนี้ใช้ไม่ได้กับคำถามเดิมแน่นอน แต่ก็ยังมีประโยชน์ที่จะรู้
efotinis

8

เว็บไซต์ NSE มีการเปลี่ยนแปลงและสคริปต์รุ่นเก่าเป็นแบบกึ่งเหมาะสมกับเว็บไซต์ปัจจุบัน ข้อมูลโค้ดนี้สามารถรวบรวมรายละเอียดการรักษาความปลอดภัยประจำวัน รายละเอียดรวมถึงสัญลักษณ์ประเภทการรักษาความปลอดภัยการปิดก่อนหน้าราคาเปิดราคาสูงราคาต่ำราคาเฉลี่ยปริมาณการซื้อขายมูลค่าการซื้อขายจำนวนการซื้อขายปริมาณที่ส่งมอบและอัตราส่วนของการส่งมอบเทียบกับการซื้อขายเป็นเปอร์เซ็นต์ สิ่งเหล่านี้นำเสนออย่างสะดวกสบายในรูปแบบพจนานุกรม

เวอร์ชัน Python 3.X พร้อมคำขอและ BeautifulSoup

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)

นอกจากนี้ยังเป็นข้อมูลโค้ดแบบแยกส่วนและพร้อมใช้งาน


ขอบคุณผู้ชาย! สิ่งนี้ใช้ได้ผลสำหรับฉันแทนที่จะเป็นคำตอบข้างต้นจาก @andrean
Nitish Kumar Pal

สวัสดีฉันไม่รู้ว่าจะต้องไปที่ไหนอีกแล้วฉันลองวิธีแก้ปัญหานี้และอื่น ๆ อีกมากมาย แต่ฉันยังคงได้รับข้อผิดพลาด 403 มีอะไรให้ฉันลองอีกไหม
Francesco

สถานะ 403 มีขึ้นเพื่อแจ้งว่าเบราว์เซอร์ของคุณไม่ได้รับการรับรองความถูกต้องเพื่อใช้บริการนี้ อาจเป็นไปได้ว่าในกรณีของคุณต้องมีการรับรองความถูกต้องด้วยการรับรองความถูกต้องขั้นพื้นฐาน oauth เป็นต้น
Supreet Sethi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.