画像ファイルのダウンロードの失敗事例です。明らかに画像取得目的の”User-Agent”でもって、数十回とリクエストしたところ、リクエストとは異なる画像ファイルが毎回送信されてくるようになりました。そして、”User-Agent”を設定し直しても続くのです。
しかし、1時間経過した後、再度正しい”User-Agent”でリクエストをしたところ、今度はダウンロードできるようになりました。
こういった現象は、サーバにアクセスが集中していると起こるようですが、アンチスクレイピングの可能性も捨てきれません。原因はともかく、確実にダウンロードができるようにする必要があります。
Pythonで画像ファイルを安全にダウンロードする簡単なサンプル
下のサンプルでは、requestsパッケージを使って、getリクストをサーバに送り画像ファイルを落としています。もちろんイメージファイルだけではなく、xlsxやmp4等の任意のファイルのダウロードが可能です。
安全にリクエストするために何をしたかというと、ブラウザからアクセスしていると分かるように設定しただけです。設定しているのは、下のサンプルコードのheaderになります。下のheaderは、Windows10からChromeでアクセスしていると仮定しています。
import requests header = { "Accept": "*/*", # MIMEタイプ "Accept-Encoding": "gzip, deflate", # 通信の圧縮形式 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "\ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" } with requests.get("https://hogehoge.com/foo.jpg", headers=header, stream=True) as res: with open("get.jpg", "wb") as f: for chunk in res.iter_content(chunk_size=1024): if chunk: f.write(chunk)
requestsにヘッダーを設定しない場合に起こること
もし、下のようにheaderを設定しないでリクストすると、”User-Agent” が ‘python-requests/2.25.1’ になります。これが、疑われる元になります。
requests.get("https://hogehoge.com/foo.jpg")
requests.get()の戻り値(詳細後述)から、送信したheaderが分かります。上のget()では、下のようなヘッダーになります。
"User-Agent": "python-requests/2.25.1", "Accept": "*/*", # MIMEタイプ "Accept-Encoding": "gzip, deflate", # 通信の圧縮形式
誤ったUser-Agentでリクエストを送った結果と確認方法
参考までに、”User-Agent”の未設定に気づいた過程を書いておきます。
これが誤った設定で数十回もリクストしたコードです。
import requests res = requests.get("https://hogehoge.com/foo.jpg") with open("get.jpg", "wb") as f: f.write(res.content)
リクエストの送信結果
res.status_code = 200 res.content = b'~' res.url = 'https://hogehoge.com/wahaha.jpg' res.request.headers
res.status_codeは、200で成功です。しかし、PC上のget.jpgは、サーバ上のfoo.jpgとは異なります。jpgのファイルサイズも違います。途中で切れているのではなく、別のjpgファイルです。
また、requestsの戻り値を見ると、https://hogehoge.com/foo.jpgをダウンロードしたいのに、https://hogehoge.com/wahaha.jpgが返されています。
“User-Agent”は、res.request.headersで確認します。
res.request.headersの内訳
'User-Agent': 'python-requests/2.25.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'
‘User-Agent’ に 機械的なアクセスと疑われる “python-requests/2.25.1” が設定されています。
そこで、先のサンプルで取得するように切り替えたところ、ダウンロードできるようになりました。
User-Agentを偽装せずに安全に画像を取得する方法
ダウンロード対象がブラウザで表示できるイメージファイルの場合、他の方法もあります。
こちらの方がサーバ側で対策される危険性がなく、メリットは絶大です。
コメント