Pythonで画像のダウンロード

計画

流れ

  • スクレイピング
  • ダウンロード

Javascriptに対応

本ブログでは、スクレイピングにBeautifulSoupを使うのでJavascriptは対応してません。SeleniumPlaywrightをご使用ください。playwrightなら

browser=await launch();
page=await browser.newPage();
selector="img" // selector
for img in await page.J(selector):
  src=await page.evaluate('(img)=>img.getAttribute("src")',img)
  if not src:
    continue

とURLを取り、後はダウンロードできると思います。

準備

モジュールのダウンロード

今回は

  • BeautifulSoup
  • requests
  • docopt

を使うのでpipで入手します。

$ pip install bs4
$ pip install requests
$ pip install docopt

コード

まずはコードを貼り解説します。

dlimg.py

from bs4 import BeautifulSoup as bs
import requests
import docopt
import sys
import os
import urllib.parse as up
import time


DEF_DL_DIR="%USERPROFILE%\Desktop\dlimage"
DEF_DL_N=10

HEADERS={
	    "User-Agent":"Mozilla/4.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"
}

def realpath(fname):
    return os.path.abspath( os.path.expanduser(os.path.expandvars(fname)))
__doc__="""
Usage:
	dlimg  [(-S <selector>)] [(-d <dname>)]
"""

def main(argv=sys.argv[1:]):
	args=docopt.docopt(__doc__,argv)
	url=args["<url>"]
	selector=args["<selector>"] or "img"
	dname=realpath(args["<dname>"] or DEF_DL_DIR)
	if not os.path.exists(dname):
		os.makedirs(dname)
	res=requests.get(url,headers=HEADERS)
	soup= bs(res.text,"html.parser")
	print("dname",dname)
	for img in soup.select(selector):
		src=img.get("src")
		if not src:
			continue
		imgurl=up.urljoin(url,src)
		fname=os.path.join(dname,"dlimg_"+str(hash(imgurl))+".jpg")
		res=requests.get(imgurl,headers=HEADERS)
		with open(fname,"wb") as f:
			f.write(res.content)
		print("downloaded",imgurl,"into",fname)
		time.sleep(1)

if __name__ == "__main__":
	main()

試す

まずは試してみます。今回はコチラの記事から画像を取ります。

$ python dlimg.py -S img.alignnone -d ero_images

downloaded http://img.eropasture.com/wp-content/uploads/2021/11/0-7.jpg into C:\Users\tetsu\code\yyy\dlimg_6956944248971562255.jpg
downloaded http://img.eropasture.com/wp-content/uploads/2021/11/danmitu_oshiri_nude_001.jpg into C:\Users\tetsu\code\yyy\dlimg_-5114313549770343638.jpg
                           :
                           :
                           :

alignnoneはwordpressの記事の投稿時に貼り付けで挿入された画像のクラスらしいです。使いまわせそうです。(笑)

では解説します。

定数、関数

定数 or 関数 名前 意味
定数 DEF_DL_DIR 未指定時のダウンロード用ディレクトリ
定数 HEADERS http通信用のヘッダー
定数 DEF_DL_DIR 未指定時のダウンロード用ディレクトリ
関数 realpath パスの展開 (%USERPROFILE% -> C:\Users\:<user_name> など)
関数 main メイン処理

引数の処理

    args=docopt.docopt(__doc__,argv)
    url=args["<url>"]
    selector=args["<selector>"] or "img"
    dname=realpath(args["dname"] or DEF_DL_DIR)
    if not os.path.exists(dname):
        os.makedirs(dname)

このコードで引数の処理をします。詳細はdocoptのページ解説記事をご覧ください。大体直感的にわかります。ざっくり言うと

引数 意味
<引数>              (例:<a>,<b>,…) 引数の指定
-<オプション>    (例:-a,-b,….) オプションの指定。1文字
–<オプション>   (例:–abc,–def,…) オプションの指定
-<オプション> <引数>    (例:-a <axx>,-b <bxx>,…) オプション付き引数の指定
–<オプション> <引数>    (例:–abc <abc>,–def <def>,…) オプション付き引数の指定
( … )    (例  : (-a <axx>),(–bcd <bcd>),…) 「…」のグループ化。必須引数
[ … ]    (例  : [-a <axx>],[–bcd <bcd>],…) 「…」のグループ化。任意引数

詳しくは上記の記事をご覧ください。

docoptで引数を処理し、ディレクトリの作成などを行います。

args[<url>] or ""

は我ながらシャレた書き方かと思っています。(笑)

 

パースしてダウンロード

res=requests.get(url,headers=HEADERS) //htmlの取得
soup= bs(res.text,"html.parser")  //スープに変換
print("dname",dname)
for img in soup.select(selector): //要素を選択
  src=img.get("src") //画像URLの取得
  if not src:
    continue
  imgurl=up.urljoin(url,src) //フルURLを取得
  fname=os.path.join(dname,"dlimg_"+str(hash(imgurl))+".jpg") //ファイル名
  res=requests.get(imgurl,headers=HEADERS) //画像の取得
  with open(fname,"wb") as f:
    f.write(res.content) //ファイルに書きこむ
  print("downloaded",imgurl,"into",fname)
  time.sleep(1)

非常にシンプルです。常々CSSセレクターの美しさに感動します。time.sleep をコメントアウトすると高速で落とせますが辞めてください。(笑)

おわりに

今回は画像を落とすプログラムを組みました。機能がシンプルなのと、それぞれに優秀で気の利いたライブラリがあるので、明快に書けました。セレクターは一々調べねばなりませんが、仕方ないですかね。

個人的には、エロ画像サイトをつくろうかなと思っているのですが、AV女優や体位や服装などを判断するためにAIやOpenCVを使おうと思っており、その学習データをご拝借(笑)するため画像を楽に落とせたらと思い作りました。あと転載のために……. 良くないですかね。まあ、お疲れさまでした!😁

コメント

タイトルとURLをコピーしました