ウェブサイトからデータを取得しようとしています。しかし、それは私を返しますincomplete read
。取得しようとしているデータは、ネストされたリンクの膨大なセットです。私はオンラインで調査を行いましたが、これはサーバーエラー(チャンク転送エンコードが予想サイズに達する前に終了する)が原因である可能性があることがわかりました。また、これに関する上記の回避策を見つけました link
しかし、私の場合にこれをどのように使用するかはわかりません。以下は私が取り組んでいるコードです
br = mechanize.Browser()
br.addheaders = [('User-agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1;Trident/5.0)')]
urls = "http://shop.o2.co.uk/mobile_phones/Pay_Monthly/smartphone/all_brands"
page = urllib2.urlopen(urls).read()
soup = BeautifulSoup(page)
links = soup.findAll('img',url=True)
for tag in links:
name = tag['alt']
tag['url'] = urlparse.urljoin(urls, tag['url'])
r = br.open(tag['url'])
page_child = br.response().read()
soup_child = BeautifulSoup(page_child)
contracts = [tag_c['value']for tag_c in soup_child.findAll('input', {"name": "tariff-duration"})]
data_usage = [tag_c['value']for tag_c in soup_child.findAll('input', {"name": "allowance"})]
print contracts
print data_usage
これで私を助けてください。ありがとう
質問に含めた link は、urllibのread()関数を実行する単なるラッパーであり、不完全な読み取り例外をキャッチします。このパッチ全体を実装したくない場合は、リンクを読み取るtry/catchループをいつでもスローできます。例えば:
try:
page = urllib2.urlopen(urls).read()
except httplib.IncompleteRead, e:
page = e.partial
python3の
try:
page = request.urlopen(urls).read()
except (http.client.IncompleteRead) as e:
page = e.partial
私の場合、HTTP/1.0リクエストを送信し、これを追加して問題を修正します。
import httplib
httplib.HTTPConnection._http_vsn = 10
httplib.HTTPConnection._http_vsn_str = 'HTTP/1.0'
私がリクエストをした後:
req = urllib2.Request(url, post, headers)
filedescriptor = urllib2.urlopen(req)
img = filedescriptor.read()
(1.1をサポートする接続用)でhttp 1.1に戻った後:
httplib.HTTPConnection._http_vsn = 11
httplib.HTTPConnection._http_vsn_str = 'HTTP/1.1'
トリックはデフォルトのhttp/1.1 http 1.1がチャンクを処理できる代わりにhttp 1.0を使用することですが、何らかの理由でWebサーバーが処理しないため、http 1.0でリクエストを実行します。
urllib2
の代わりにrequests
を使用できます。 requests
はurllib3
に基づいているため、ほとんど問題はありません。ループに入れて3回試してみると、はるかに強力になります。次のように使用できます。
import requests
msg = None
for i in [1,2,3]:
try:
r = requests.get(self.crawling, timeout=30)
msg = r.text
if msg: break
except Exception as e:
sys.stderr.write('Got error when requesting URL "' + self.crawling + '": ' + str(e) + '\n')
if i == 3 :
sys.stderr.write('{0.filename}@{0.lineno}: Failed requesting from URL "{1}" ==> {2}\n'. format(inspect.getframeinfo(inspect.currentframe()), self.crawling, e))
raise e
time.sleep(10*(i-1))
私のために働いたのは、IncompleteReadを例外としてキャッチし、これを以下のようなループに入れることで、各繰り返しで読み取ることができたデータを収集することです:(注、私はPython 3.4.1とurllibライブラリは2.7と3.4の間で変更されました)
try:
requestObj = urllib.request.urlopen(url, data)
responseJSON=""
while True:
try:
responseJSONpart = requestObj.read()
except http.client.IncompleteRead as icread:
responseJSON = responseJSON + icread.partial.decode('utf-8')
continue
else:
responseJSON = responseJSON + responseJSONpart.decode('utf-8')
break
return json.loads(responseJSON)
except Exception as RESTex:
print("Exception occurred making REST call: " + RESTex.__str__())
ウイルス検出器/ファイアウォールがこの問題を引き起こしていることがわかりました。 AVGの「オンラインシールド」部分。