urllib2.HTTPError:HTTPエラー403:禁止


102

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でHTTPError(req.get_full_url()、code、msg、hdrs、fp)を発生させるurllib2.HTTPError:HTTPエラー403:禁止

ご協力ありがとうございます


Windowsをプラットフォームとして使用していますか?
Denis

回答:


170

いくつかのヘッダーを追加することで、データを取得できました。

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

実際、これは次の1つの追加ヘッダーでのみ機能します。

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

これらのヘッダーのうち、元のリクエストから欠落していたと思うものはどれですか。

1
Wiresharkは、User-Agentのみが送信され、接続:close、ホスト:www.nseindia.com、Accept-Encoding:identity
andrean

1
どういたしまして、私が実際に行ったことは、ブラウザーでスクリプトからURLを確認し、そこで機能するように、ブラウザーが送信したすべての要求ヘッダーをコピーしてここに追加しただけで、それが解決策でした。
andrean

1
@Mee以下の答えを見てみましたか?具体的にはpython 3で対処されました。動作するかどうかを確認してください...
andrean

1
(私の回答から)他のヘッダーもリクエストに追加してみてください。それでもサーバーが403を返す理由は他にもたくさんあります。このトピックに関する他の回答も確認してください。ターゲットに関しては、グーグルは特にタフなもので、スクレイピングがちょっと難しいです。スクレイピングを防ぐために多くの方法を実装しています。
andrean

50

これは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のライブラリーから送信された「Python-urllib / xy」のように、一般的な非ブラウザーのユーザーエージェント文字列をブロックするのは事実です。単純な「Mozilla」または「Opera」でさえ、通常はそれをバイパスするのに十分です。もちろん、これは元の質問には当てはまりませんが、知っておくと役に立ちます。
efotinis 2013

7

NSE Webサイトが変更され、古いスクリプトは現在のWebサイトに準最適です。このスニペットは、セキュリティの毎日の詳細を収集できます。詳細には、シンボル、セキュリティタイプ、前回の終値、始値、高値、安値、平均価格、取引数量、取引高、取引数、成果物の数量、および配信された取引と取引された比率の割合が含まれます。これらは、辞書形式のリストとして便利に表示されます。

リクエストと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)

さらに、これは比較的モジュール式であり、スニペットを使用する準備ができています。


ありがとう!これは、@ andreanからの上記の回答の代わりに私のために機能しました
Nitish Kumar Pal

こんにちは、本当に頭を叩く場所が本当にわかりません。私はこの解決策などを試しましたが、エラー403が発生し続けます。他に試すことはできますか?
フランチェスコ

403ステータスは、ブラウザがこのサービスを使用するために認証されていないことを通知するためのものです。あなたの場合、それは本当に基本的なauth、oauthなどでの認証を本当に必要とするかもしれません
Supreet Sethi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.