ひさふぃの日記

DjangoとPythonとLaravelが好き。大阪でフリーランスエンジニアやってます。

Python|サイトの画像を一括ダウンロード

サイトの画像を一括でダウンロードする必要がありましたので、Pythonにてサクッと書きました。

過去の偉人達が煎じまくっていて味が出ない内容ですが、未来の自分のためにメモ。あと、もしかしたら誰かの役に立つかもしれませんしね。

環境

python=3.6.0
macOS Sierra==10.12.6

最初に必要なモジュールを導入します。

pip install bs4 requests lxml

今回入ったモジュールのバージョン

beautifulsoup4==4.6.0
bs4==0.0.1
certifi==2017.4.17
chardet==3.0.4
idna==2.5
lxml==3.8.0
requests==2.18.1
urllib3==1.21.1

おまじないとMainクラス

最初におまじない。次に、コードを使用時にインスタンス化するクラスMainを記述しています。

Mainクラスは、コンストラクタでUrlListCollectorとImage_DLをインスタンス化して使用。

UrlListCollectorは、urlを引数として渡し、サイト内の画像のurlのリストを取得。

Image_DLは、画像のurlと保存するディレクトリの名前を引数として渡し、画像を保存。

どちらのクラスも詳細は後述。

# -*- coding: utf-8 -*-

from bs4 import BeautifulSoup
import requests
import re, os

class Main:
    def __init__(self):
        self.collector = UrlListCollector()
        self.downloader = Image_DL()

    def do(self, url, dir_name):
        url_list = self.collector.get(url)
        for image_url in url_list:
            self.downloader.save(image_url, dir_name)
        print("complete")

UrlListCollectorクラス

RequestsAndBS4Gatewayクラスをコンストラクトで受け取っています。こちらはrequestsとbs4モジュールでいい感じに処理してくれるクラス。

getメソッドでは、RequestsAndBS4Gatewayクラスより受け取ったbs4のオブジェクトから、hrefに".jpg"文字列を含むaタグを取得しています。

url_listでは、lambda式を使用して画像urlのセットを作成。

この際、hrefで取得する文字列の前半に必要なurlを記述しています。下のコードでは、http://hogehoge.netの部分です。サイトのソースコードを確認して書き換えます。

class UrlListCollector:
    def __init__(self):
        self.getting_gateway = RequestsAndBS4Gateway()

    def get(self, url):
        soup = self.getting_gateway.get_and_parse(url)
        tag = soup.find_all('a',href=re.compile(".jpg"))
        url_list = {'http://hogehoge.net{}'.format(i["href"]) for i in tag}
        return url_list

class RequestsAndBS4Gateway:
    def get_and_parse(self, url):
        soup_content = []
        req = requests.get(url)
        req.encoding = "utf-8"
        soup_content = BeautifulSoup(req.text, "lxml")
        return soup_content

Image_DLクラス

saveメソッドでは、画像urlとディレクトリの名前から画像を保存します。

os.getcwdは、カレントディレクトリの文字列を取得。

今回は使用していませんがファイル名を変更したい場合は、三つ目の引数nameに新たなファイル名を渡してあげます。

class Image_DL():
    def save(self, image_url, dir_name, name=None):
        path = os.getcwd()+"/"+dir_name+"/"
        if name==None:
            path += url.split("/")[-1]
        else:
            path += name
        res = requests.get(url)
        with open(path, 'wb') as file:
            file.write(res.content)

さいごに

上記のコードをコピペして、UrlListCollectorのlambda式に使用するサイトurlを書き換えれば使えます。

サイトのソースコードを参照する点がイケてませんが、書き捨てのコードなので細かいことはいいでしょ!

最後までお読みいただきありがとうございます。それじゃ!