シャニマスの全R~SSR画像を保存するスクリプト


アイドルマスター シャイニーカラーズ、絵が良い。そんなシャイニーカラーズ(以下、シャニマス)の画像を全部保存したくありませんか?

ただ、シャニマスのキャラって今(2019/10/01現在)252種類あるわけで...一つ一つページ探して保存するのはめんどくさいんですよね...

そこで!!スクレイピングを使って全部勝手に保存してもらおう!というわけです。

注意!!

上を読んでもらった方が早いんですけど著作権法などの絡みがあるっていうのとサーバーに負担をかけてしまう行為なので慎重に行ってください。

使用環境

Windows 10 Education
Python 3.7.3

ソースコード

shiny_scraping.py
import requests 
from bs4 import BeautifulSoup as bs
import os
import urllib.request
import urllib.error
j = 0

for num in range(1, 253):
    URL = 'https://imas-shinycolors.boom-app.wiki/entry/card-' + str(num) # URL入力
    images = [] # 画像リストの配列
    soup = bs(requests.get(URL).content,'lxml') # bsでURL内を解析
    for link in soup.find_all("img"): # imgタグを取得しlinkに格納
        s = link.get("src")
        if s.endswith("w=960") or s.endswith("w=600"):
            images.append(link.get("src"))

    for img in images:
        j += 1
        try:
            with urllib.request.urlopen(img) as w:
                data = w.read()
                with open('C:/Users/[ユーザー名]/Pictures/ShinyColors/' + str(j) + '.jpg', mode='wb') as m:
                    m.write(data)
        except urllib.error.URLError as e:
            print(e) #保存できなかった時のため

    print("No." + str(num) + " is ok") # 確認

解説

前半部分



for num in range(1, 253):
    URL = 'https://imas-shinycolors.boom-app.wiki/entry/card-' + str(num) # URL入力
    images = [] # 画像リストの配列
    soup = bs(requests.get(URL).content,'lxml') # bsでURL内を解析
    for link in soup.find_all("img"): # imgタグを取得しlinkに格納
        s = link.get("src")
        if s.endswith("w=960") or s.endswith("w=600"):
            images.append(link.get("src"))

1行目...今回はシャニマス攻略wikiを使って抜き出していこうと思います。252種類あるのでrangeを1~253にして(Pythonを使ったことある人は分かると思いますが、範囲指定は必要な数+1します)、
2行目...URLに番号を含めたものを指定します。
3行目...画像urlを格納するリストを初期化します
4行目...2行目で定義したURLの中身を取得します。この時の内容はlxml形式で取得されます。

基本的にスクレイピングは、ページを構成しているhtmlから必要な情報をタグやid、クラスなどを指定することで取得する感じになります。例えば、【ほわっとスマイル】櫻木真乃の場合だと、

URL: https://imas-shinycolors.boom-app.wiki/entry/card-1 

の中は以下の通りになっています。

card-1

<!DOCTYPE html>
<html lang="ja" xmlns:og="http://ogp.me/ns#">
<head>
<meta charset="UTF-8">
(略)

    <div class="breadcrumbs">
        <ul>
            <li><a href="/"><i class="fa fa-home" aria-hidden="true"></i> シャニマス攻略Wiki</a></li>
            <li><a href="https://imas-shinycolors.boom-app.wiki/entry/card-list">全カード一覧</a></li>            <li>SSR【ほわっとスマイル】櫻木真乃のスキルとステータス</li>

(略)

<div class="imgList1">

<div class="ss"><div class="image-zoom" data-url="https://image.boom-app.wiki/wiki/5a824ae1b1b4b803847278d1/35a59c77b6e647b3c56a66662fa46329.jpg?w=600">
<img src="https://image.boom-app.wiki/wiki/5a824ae1b1b4b803847278d1/35a59c77b6e647b3c56a66662fa46329.jpg?w=600" alt="">
</div>
</div>
</div>

(略)

<h3>フェスアイドルイラスト</h3>
<div class="imgList1">
<div class="ss"><div class="image-zoom" data-url="https://image.boom-app.wiki/wiki/5a824ae1b1b4b803847278d1/card/fes/001.jpg?w=960">
<img src="https://image.boom-app.wiki/wiki/5a824ae1b1b4b803847278d1/card/fes/001.jpg?w=960" alt="【ほわっとスマイル】櫻木真乃">
</div>
</div>
</div>


<a name="toc2" id="toc2"></a>
<h2>SSR【ほわっとスマイル】櫻木真乃の演出まとめ</h2>


(略)

</body>
</html>

今回取得したい画像(通常絵、フェスアピール時絵)は、いずれも.jpgの後に?w=600 or 960がついているのがわかると思います、これによって画像の幅を指定しているのですが、今回はこれを逆手にとってこの2種類の画像のみを取得するようにします。

5行目から...4行目で取得したもののなかからimgタグの文のみを指定し、その中でも上記の通り、?w=960?w=600で終わっているものを指定し、取得します。(これがないと、結構色々な画像が入ってしまうので選別が大変なことになります。)取得したいもの(リンク形式になっている)をimagesリストに格納します。

後半部分


    for img in images:
        j += 1
        try:
            with urllib.request.urlopen(img) as w:
                data = w.read()
                with open('C:/Users/[ユーザー名]/Pictures/ShinyColors/' + str(j) + '.jpg', mode='wb') as m:
                    m.write(data)
        except urllib.error.URLError as e:
            print(e) #保存できなかった時のため
    print("No." + str(num) + " is ok") # 確認

1~2行目...1imagesリストのなかから1枚ずつ取り出します。今回は保存するときの画像名を「(番号).jpg」にしたかったので上でjという引数を用意し、1枚画像を保存するごとに1ずつ加えています。
3~7行目...1枚ずつリンクの画像を読み込んで取得したものをopenの第一引数で指定したフォルダに保存しています。
8~9行目...取得できなかったらどういうエラーが起こったかをターミナルに出力します
10行目...コンソールに進捗を書き出しています。

実行結果


実行すると1つずつこんな感じで実行されます。だいたい1つ実行するのに0.5~1秒かかるので3分ほどで終わると思います。

この通り、見事に保存されていることがわかります。是非法の範囲で使って見てください~