LoginSignup
1
0

More than 3 years have passed since last update.

URLを記載したテキストファイルから画像をダウンロード

Posted at

はじめに

  • 実は、$ wget -i urls.txt の様な感じで、画像を次々ダウンロードしてくれます。
  • ただし、画像が存在しないと、.html.txt がダウンロードされたりします。
  • 今回は、Content-Type の確認、画像データの確認、一律 .jpeg へ変換等を実施します。
  • 前回の記事は、Google カスタム検索エンジンで画像リンクを取得する です。
  • ソース一式は ここ です。

ライブラリのインストール

  • URL から画像をダウンロードする requests
  • 画像データの確認、変換する pillow
$ pip install pillow requests

設定ファイル config.py

  • 下記の様に、URLファイルは、CLASSESLINK_PATH を元に参照されます。
  • また、DOWNLOAD_PATH に画像をダウンロードします。
  • 詳しくは、前回の記事を確認して頂ければと思います。
$ cat config.py


CLASSES = [
    '安倍乙',
    '石原さとみ',
    '大原優乃',
    '小芝風花',
    '川口春奈',
    '森七菜',
    '浜辺美波',
    '清原果耶',
    '福原遥',
    '黒島結菜'
]


BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATA_PATH = os.path.join(BASE_PATH, 'data')
LINK_PATH = os.path.join(DATA_PATH, 'link')
DOWNLOAD_PATH = os.path.join(DATA_PATH, 'download')

URL を記載したテキストファイル

  • 以下の様なファイルです。
$ head 黒島結菜.txt
http://cm-watch.net/wp-content/uploads/2018/03/b22dc3193fd35ebb1bf7aa4e74c8cffb.jpg
https://www.crank-in.net/img/db/1165407_650.jpg
https://media.image.infoseek.co.jp/isnews/photos/hwchannel/hwchannel_20191107_7062003_0-small.jpg
https://i.pinimg.com/originals/3e/3c/61/3e3c61df2f426a8e4623b58d84d94b40.jpg
http://yukutaku.net/blog/wp-content/uploads/wordpress-popular-posts/253-100x100.jpg
http://gratitude8888.biz/wp-content/uploads/2017/03/cb1175590da467bef3600df48eabf770.jpg
https://www.cinemacafe.net/imgs/p/ATDRThl-6oWF9fpps9341csCOg8ODQwLCgkI/416673.jpg
https://s3-ap-northeast-1.amazonaws.com/moviche-uploads/wp-content/uploads/2019/10/IMG_2547.jpg
https://scontent-frx5-1.cdninstagram.com/vp/05d6926fed565f82247879638771ee46/5E259FCC/t51.2885-15/e35/67735702_2288175727962135_1310736136046930744_n.jpg?_nc_ht=scontent-frx5-1.cdninstagram.com&_nc_cat=103&se=7&ig_cache_key=MjEyMzM1MTc4NDkyMzQ4NzgxMg%3D%3D.2
http://moco-garden.com/wp-content/uploads/2016/05/kurosimayuina.jpg

画像のダウンロード、チェックと保存

URL を記載したテキストファイルの読み込み

  • 前回作成した URL を改行で記載したファイルを読み込みます。
def download(query):
    """データのダウンロード、データのチェック、画像の保存."""

    linkfile = os.path.join(LINK_PATH, '{}.txt'.format(query))
    if not os.path.isfile(linkfile):
        print('no linkfile: {}'.format(linkfile))
        return

    with open(linkfile, 'r') as fin:
        link_list = fin.read().split('\n')[:-1]

画像のダウンロードと Content-Type の確認

  • 上記で読み込んだ URL のリストデータを元に、次々ダウンロードをします。
  • Content-Typeimage/ で始まっている事を確認します。
  • image/ は、jpeg png gif bmp だったりしますね。
    for num, link in enumerate(link_list, start=1):

        try:
            result = requests.get(link)
            content = result.content
            content_type = result.headers['Content-Type']
        except Exception as err:
            print('err: {}, link: {}'.format(err, link))
            continue

        if not content_type.startswith('image/'):
            print('err: {}, link: {}'.format(content_type, link))
            continue

pillow での画像読み込み設定

  • 以下を設定すると、サイズの大きい画像も読み込んでくれる様になります。
ImageFile.LOAD_TRUNCATED_IMAGES = True

画像データのチェック

  • pillow で画像データを読み込みます。
  • 読み込めなければ、画像データは壊れている確率が高いです。
        try:
            image = Image.open(io.BytesIO(content))
        except Exception as err:
            print('err: {}, link: {}'.format(err, link))
            continue

画像データを .jpeg へ変換

  • 後工程の事を考えると、いちいち .png.bmp の場合を考慮しながら処理をするのは面倒だと思ってます。
  • そこで、一律 .jpeg へ変換します。
  • RGBA 等の場合があるので、.jpegRGB に変換します。
        if image.mode != 'RGB':
            image = image.convert('RGB')
        data = io.BytesIO()
        image.save(data, 'jpeg', optimize=True, quality=95)
        content = data.getvalue()

画像の保存

  • 設定フィアルに記載の DOWNLOAD_PATH に従い、0001.jpeg 0002.jpeg などの様なファイル名で保存します。
  • URL の末尾を利用してファイル名にする事は無いと思います。
  • また、URL のテキストファイルの行数とファイル名の数字が一致しているので、お互いに参照がしやすいと思います。
        filename = os.path.join(DOWNLOAD_PATH, query, '{:04d}.jpeg'.format(num))
        with open(filename, 'wb') as fout:
            fout.write(content)
        print('query: {}, filename: {}, link: {}'.format(query, os.path.basename(filename), link))

ダウンロード、ファイル処理時のエラーの例

  • URL は、だいたい 6,000 位でした。その内、約 180 がエラーでした。
  • エラーは、以下の様な感じです。
  • 画像データではなく、html だったりします。
  • ただし、Content-Typeapplication/octet-streambinary/octet-stream は、画像データとして保存出来るはずですが、今回は数も少ないので省きました。
$ awk '{print $2}' err.txt | sort | uniq -c | sort -nr
  47 text/html;
  31 text/plain,
  30 ('Connection
  27 text/html,
  18 'content-type',
  10 cannot
   5 application/octet-stream,
   2 application/xml,
   1 images
   1 binary/octet-stream,
   1 UserWarning:
   1 HTTPSConnectionPool(host='jpnews24h.com',
   1 HTTPSConnectionPool(host='host-your-site.net',
   1 HTTPSConnectionPool(host='gamers.co.jp',
   1 HTTPConnectionPool(host='youtube.dojin.com',
   1 HTTPConnectionPool(host='nosh.media',
   1 HTTPConnectionPool(host='arukunews.jp',
   1 Exceeded

おわりに

  • $ wget -i urls.txt では、ちょっと手が届かないかゆい部分に対応しました。
  • 次回は、画像から顔認識を実施する予定です。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0