pythonソケット.エラー: [Errno 10054] リモートホストが既存の接続を強制的に閉じました。問題の解決策:
数日前、Python を使用して Web ページを読みました。 Web サイトでは多数の urlopen 操作が使用されるため、その Web サイトによる攻撃とみなされます。ダウンロードが許可されなくなる場合があります。その結果、request.read() は urlopen() の後にスタックしてしまいました。最後に、errno 10054 がスローされます。
このエラーは、ピアによる接続のリセットです。つまり、伝説的なリモート ホストが接続をリセットしました。原因としては、ソケットのタイムアウトが長すぎることが考えられます。request = urllib.request.urlopen(url); の後に request.close() 操作が実行されなかったり、いくつかのスリープが存在しなかったりする可能性があります。これにより、Web サイトはこの動作が攻撃であると認識します。
具体的な解決策は次のとおりです:
01.import socket 02.import time 03.timeout = 20 04.socket.setdefaulttimeout(timeout)#这里对整个socket层设置超时时间。后续文件中如果再使用到socket,不必再设置 05.sleep_download_time = 10 06.time.sleep(sleep_download_time) #这里时间自己设定 07.request = urllib.request.urlopen(url)#这里是要读取内容的url 08.content = request.read()#读取,一般会在这里报异常 09.request.close()#记得要关闭
urlopen の後の read() 操作は実際にソケット層の特定の関数を呼び出すためです。したがって、デフォルトのソケット タイムアウトを設定すると、ネットワーク自体が切断される可能性があります。 read()で待つ必要はありません。
もちろん、外側の層を除いて、さらにいくつかの try を記述することもできます。たとえば、
try: time.sleep(self.sleep_download_time) request = urllib.request.urlopen(url) content = request.read() request.close() except UnicodeDecodeError as e: print('-----UnicodeDecodeError url:',url) except urllib.error.URLError as e: print("-----urlError url:",url) except socket.timeout as e: print("-----socket timout:",url)
一般的には問題ありません。これを言う前に、私は何千もの Web ページのダウンロードをテストしました。ただし、何千ものファイルをダウンロードした場合、私がテストを行ったところ、MS は依然としてこの例外から抜け出します。 time.sleep() の時間が短すぎるか、ネットワークが突然中断された可能性があります。 urllib.request.retrieve() を使用してテストしたところ、データのダウンロードを続けると常に失敗することがわかりました。
簡単な解決策は次のとおりです。まず、私の記事「Python チェックポイントの簡単な実装」を参照してください。まずはチェックポイントを作ります。次に、例外を発生させる上記のコードを while True に変更します。以下の疑似コードを参照してください:
def Download_auto(downloadlist,fun,sleep_time=15): while True: try: # 外包一层try value = fun(downloadlist,sleep_time) # 这里的fun是你的下载函数,我当函数指针传进来。 # 只有正常执行方能退出。 if value == Util.SUCCESS: break except : # 如果发生了10054或者IOError或者XXXError sleep_time += 5 #多睡5秒,重新执行以上的download.因为做了检查点的缘故,上面的程序会从抛出异常的地方继续执行。防止了因为网络连接不稳定带来的程序中断。 print('enlarge sleep time:',sleep_time)
ただし、対応する Web ページが見つからない場合は、別のプロセスを実行する必要があります:
# 打印下载信息 def reporthook(blocks_read, block_size, total_size): if not blocks_read: print ('Connection opened') if total_size < 0: print ('Read %d blocks' % blocks_read) else: # 如果找不到,页面不存在,可能totalsize就是0,不能计算百分比 print('downloading:%d MB, totalsize:%d MB' % (blocks_read*block_size/1048576.0,total_size/1048576.0)) def Download(path,url): #url = 'http://downloads.sourceforge.net/sourceforge/alliancep2p/Alliance-v1.0.6.jar' #filename = url.rsplit("/")[-1] try: # python自带的下载函数 urllib.request.urlretrieve(url, path, reporthook) except IOError as e: # 如果找不到,好像会引发IOError。 print("download ",url,"/nerror:",e) print("Done:%s/nCopy to:%s" %(url,path))
それでも問題が発生する場合は、他の解決策をコメントに記入してください。