計画
流れ
- スクレイピング
- ダウンロード
Javascriptに対応
本ブログでは、スクレイピングにBeautifulSoupを使うのでJavascriptは対応してません。SeleniumやPlaywrightをご使用ください。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を使おうと思っており、その学習データをご拝借(笑)するため画像を楽に落とせたらと思い作りました。あと転載のために……. 良くないですかね。まあ、お疲れさまでした!😁
コメント