Cute is better than ugly.

かわいいものを追求しているエンジニアのブログです

うえしゃまの画像何マイ持ってる?

先週はミリオンライブ6th追加公演お疲れさまでした。
運良く二日間とも現地参戦し、楽しい時間を過ごせました。

今回は、そんなライブに行ったテンションの高さと上田麗奈さんがかわいかったので
観賞用に上田麗奈さんの画像をたくさん集めてしまおうと考えました。
そうです、スクレイピングです。

環境

言語: Python 3.6
ライブラリ: Selenium

pip install selenium

やりたいこと

単純にGoogleにある画像を引っ張ってくると取捨するのが面倒くさいので、
今回は上田麗奈さんが去年まで連載していたWebコラム上田麗奈の『この色、いいな』の画像をローカル上に保管するようにします。
※画像については私的使用のための複製となります。

正直これ以降のスクレイピングについての記事は読まなくていいので『この色、いいな』を見て上田麗奈ファンになろう。

やったこと

コード

そのままコードを使っても動作しないよう、取得しているタグ名などは省略しています。

from selenium import webdriver
import urllib.request as req
import os
import time

driver = webdriver.Chrome('I:/programing/tool/chromedriver.exe')

driver.get("https://webnewtype.com/column/color/")
time.sleep(3)


def articls():
    for i in range(4, 5):
        if i != 1:
            driver.get(driver.current_url + "p" + str(i) + "/")

        listBox = driver.find_element_by_class_name('')
        articls = listBox.find_elements_by_css_selector('')

        for article in articls:
            next_url = article.find_element_by_tag_name().get_attribute()
            # 個別記事は別ウィンドウで表示する
            driver.execute_script("window.open()")
            driver.switch_to.window(driver.window_handles[1])
            driver.get(next_url)
            time.sleep(1)
            images(driver.current_url)
            driver.close()
            driver.switch_to.window(driver.window_handles[0])


def images(base_url: str):
    image_count = 1
    title_box = driver.find_element_by_class_name('')
    title = title_box.find_element_by_tag_name('').text
    while True:
        url = base_url + str(image_count)
        # 画像先URLへ移動
        driver.get(url)
        time.sleep(1)

        try:
            image_box = driver.find_element_by_class_name('')
            image_url = image_box.find_element_by_class_name('').get_attribute('')
            image = req.urlopen(image_url).read()
            save_image(image, title, image_count)

            time.sleep(1)
            image_count += 1
        except:
            # 要素が存在しない場合はfind_element時に例外が発生するので、それ以上の処理を行わない
            break


def save_image(image, name, count):
    if not os.path.exists('./image'):
        os.mkdir('./image')
    if not os.path.exists('./image/' + name):
        os.mkdir('./image/' + name)
    print('./image/' + name + '/' + str(count) + '.jpg')
    with open('./image/' + name + '/' + str(count) + '.jpg', mode='wb') as f:
        f.write(image)
    print('donwload: {}'.format(name + '/' + str(count)))


if __name__ == '__main__':
    articls()

コードについて

別ウィンドウでの表示
driver.execute_script("window.open()")
driver.switch_to.window(driver.window_handles[1])
driver.get(url)
# 別タブでの操作処理
driver.close()
driver.switch_to.window(driver.window_handles[0])

上記の様にかくことで、別タブでの操作を行える。
わざわざこの書き方をしたのは、メイン画面で各個別記事のURLを取得していたのだが画面遷移するとどうにもその値が消えてしまっていたからだ。
うまく文字で表現しにくいのだが、

メイン画面

各個別記事のURLを取得(変数:urlsとする)

(A)個別記事分ループ処理を行う

個別記事[i]に移動

画像取得

(A)へ戻る

この場合に、(A)に戻るとurlsの値が消えてしまっていた。
seleniumのコードを読んだわけではないので実際の処理はどうかわからないが仮説として
seleniumfind_elementを使用してメモリ上に値を格納するわけだが、これはページ遷移すると前の画面で使用していたメモリを解放しているんじゃないだろうか
そのせいでurlsに格納していたはずの値は解放されてしまい、ループに戻ってもその分のメモリ領域は確保しているが値自体は無くなっている気がする。

こういった理由から、urlsを保管するために個別記事は別タブで操作している。

スクレイピングについて

不慣れなこともあるが実装に1~2時間程度かかってしまったが、
汎用的なものではないので他のサイトから画像を取得する場合も同様に時間がかかることを考えると
ある程度の規模のサイトであれば手動で画像を保管していく方が手っ取り早いのかもしれないなと思った。
今回の上田麗奈さんのフォトコラムだと80記事近くあり、画像枚数だと1500枚以上になるのでさすがに作った方が早かった。

f:id:ponny_anna:20190929223556p:plain

さいごに

とにもかくにも大量の上田麗奈さん画像(ちょいちょい唐揚げこと南早紀がいたりします)が手に入ったので良しとします。
次はこの画像を使っていい感じにスライドして表示してくれるようなツールを作ってもいいかもしれないなと思っています。

最後になりますが、上田麗奈さんがフォトブックを発売されるのでこの記事を見て上田麗奈さんに興味を持たれたら購入してください。
私は、種田梨沙推しなので買うかどうかはわかりませんが。