この記事は, Pythonを利用して研究を行なっていく中で私がつまずいてしまったポイントをまとめていくものです。同じような状況で苦しんでいる方々の参考になれば嬉しいです。Pythonつまずきポイント集の目次は以下のページをご覧ください。
環境
●Ubuntu 18.04
●Python 3.7.3
●conda 4.8.3
●pytorch 1.2.0
やりたいこと
Web上のファイルを手作業で一回一回ダウンロードするのは面倒くさいから取得のためのURLを利用してPythonスクリプトを回して一括保存したい。
実現方法
「urllib.request.urlretrieve」を利用します。例えば,「https://hoge.com」というサイトからファイルをダウンロードしたいとします。試しに手作業で1つのファイルをダウンロードしてみると,「https://hoge.com/download/0」というURLに一瞬リダイレクトされ,ローカルのダウンロード先にしているディレクトリにファイルが保存されることが分かったとします。
すると,単純には「https://hoge.com/download/0」「https://hoge.com/download/1」…のようにしてURLの最後の部分を0,1,2…のように変えていってURLにアクセスすればよいことになります。そこで便利な関数が「urllib.request.urlretrieve」です。
この関数は返り値は「local_filename」と「headers」です。例えば,headersにはファイルサイズの情報やファイル名の情報などが格納されています。
import urllib.request
local_filename, headers = urllib.request.urlretrieve("https://python.org/")
print(local_filename)
print(headers)
print(int(headers["content-length"]))
# local_filename
/tmp/tmp7b_gcasi
# headers
Server: nginx
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY
Via: 1.1 vegur
Via: 1.1 varnish
Content-Length: 48797
Accept-Ranges: bytes
Date: Sun, 12 Apr 2020 03:55:28 GMT
Via: 1.1 varnish
Age: 650
Connection: close
......
# int(headers["content_length"])
48797
さて,この関数の2つ目の引数に「output_path」つまりダウンロード先のパスを指定してあげると,指定先にURLで指定したファイルがダウンロードされるという仕様になっています。
# ダウンロードの実行
url = "https://hoge.com/0"
output_path = "/home/[your username]/Downloads/dataset"
urllib.request.urlretrieve(url, output_path)
これをひたすら繰り返せば良いわけです。単純にはwhileを使ってループしていけばOKです。その際,tryを使えば例えばファイルのサイズが極端に大きい場合や小さい場合にダウンロードをスキップするなどの工夫が可能です。
import urllib.request
import os
url = "https://hoge.com/"
output_path = "/home/[your username]/Downloads/dataset/"
count = 0
while count < 999:
this_file = url + str(count)
# 例えば拡張子が.txtのとき
this_name = output_path + str(count) + ".txt"
try:
_, headers = urllib.request.urlretrieve(this_file, this_name)
# 10bytes以下か1GB以上は消去
if (int(headers["content-length"]) < 10) or (int(headers["content-length"]) > 1e9:
os.remove(this_name)
except:
print("ダウンロード失敗")
count += 1
ここで,urllib.request.urlretrieveを実行している時点でos.removeしなくては小さすぎるファイルや大きすぎるファイルを削除することができませんので注意して下さい。