リンク先の画像をまとめて保存するpythonスクリプト

珍しく仕事のデータ形式に依存しないスクリプトを書いたので,調べたことなどを忘れないように.

ソース

#! /usr/bin/python
# coding: utf-8

import subprocess
import re
import sys
# import codecs
import os
import urllib2

IMGURL = re.compile(ur'http.*?\.jpg|JPG|jpeg|JPEG')

inputurl = sys.argv[1]
inputhtml = urllib2.urlopen(inputurl)
html = inputhtml.readlines()

target_lines = []
for line in html:
    for imgline in IMGURL.findall(line):
        target_lines.append(imgline)

dirname = re.sub(u'https?://', u'',inputurl).replace(u'/', u'--') + u'_imgs'
os.mkdir(dirname)
os.chdir(dirname)

for url in target_lines:
    getimg = subprocess.call([u'wget', url])

inputhtml.close()

使い方

$ python scriptname.py URL

やってること

  • 使うモジュールのインポート
import subprocess
import re
import sys
import os
import urllib2
  • ページ内の画像リンクを抽出するための正規表現文字列を指定
IMGURL = re.compile(ur'http.*?\.jpg|JPG|jpeg|JPEG')
  • URLからHTMLソースを行ごとに取得
inputurl = sys.argv[1]
inputhtml = urllib2.urlopen(inputurl)
html = inputhtml.readlines()
  • 各行にある画像のURLをパターンマッチングで取得し,URLのリストを作る
target_lines = []
for line in html:
    for imgline in IMGURL.findall(line):
        target_lines.append(imgline)
  • 保存用のフォルダをカレントディレクトリの直下に作り,移動
dirname = re.sub(u'https?://', u'',inputurl).replace(u'/', u'--') + u'_imgs'
os.mkdir(dirname)
os.chdir(dirname)
  • 取得したURLから画像を保存
for url in target_lines:
    getimg = subprocess.call([u'wget', url])
  • ファイルを閉じる
inputhtml.close()

余談

urllib2とwget

urllib2(pythonのモジュール),wget(シェルコマンド)がインストールされていないかもしれない.
前者はpipで

$ pip install urllib2

後者はhomebrewで

$ brew install wget

で取得.pipおよびhomebrewのインストールや使い方については調べてください.

保存するファイル
IMGURL = re.compile(ur'http.*?\.jpg|JPG|jpeg|JPEG')

単に拡張子でファイル形式を指定しているだけなので,ここを変更すれば保存するファイルを変えられる.

with codecs.open()とurllib2の組み合わせ
# import codecs
import urllib2

inputurl = sys.argv[1]
inputhtml = urllib2.urlopen(inputurl)
html = inputhtml.readlines()

inputhtml.close()

urllib2.urllibopen() はwith codecs.open()では開けなかったが,なにかやり方があるんだろうか.
おかげで時々UnicodeDecodeErrorが出る
# ソースhtmlのエンコーディングによるらしい
# sys.setdefaultencoding('utf-8')は試していない

保存先とos.mkdir()の仕様
dirname = re.sub(u'https?://', u'',inputurl).replace(u'/', u'--') + u'_imgs'

フォルダ名はURLから作成
http(s)://を削除し,/を--に置き換えている
/のままだとosモジュールにpathだと認識されてしまい,.mkdirでは再帰的にフォルダが作れない旨のエラーが出る

やってもいいかも

IMGURL = re.compile(ur'http.*?\.jpg|JPG|jpeg|JPEG')

jpg|JPG|jpeg|JPEG のところをコマンドライン引数で指定するようにしてもいいと思う.

18/06/21追記

urllibにurllib.urlretrieve(url, file)というのがあるらしい.

How do I download a file over HTTP using Python? - Stack Overflow