乃木坂46ブログの画像を全自動保存するプログラム

#はじめに
こんにちは．
坂道オタクの@tfujitaniです．
今回は乃木坂46の指定したメンバーのブログの画像を全自動で保存できるようなPythonを作成したので公開します．
ちなみにこのプログラムを作ろうと思った[”きっかけ”](https://www.youtube.com/watch?v=6W8mmtgeOzY)としては，推しだった井上小百合さんが卒業する（した）ためです．（きっかけ，いい歌ですよね．）
そのために作成したプログラムを今更ですが公開します．

#今回やったこと
##用いたもの
・Python
・BeautifulSoup

### スクレイピング環境のインストール
```
pip install requests
pip install beautifulsoup4
```

## Pythonコード
Beautiful SoupとPython3を用いてスクレイピングしています．
今回は指定したいメンバーのブログURLを指定します．
秋元真夏さん（ http://blog.nogizaka46.com/manatsu.akimoto/ ）なら"manatsu.akimoto"
伊藤理々杏ちゃん（ http://blog.nogizaka46.com/riria.itou/ ）なら"riria.itou"という感じです．
さらに，保存したい期間の始点と終点も指定できます．

```python:nogiblog.py
# coding:utf-8
from time import sleep
import time
from bs4 import BeautifulSoup
import sys
import requests, urllib.request, os
from selenium.common.exceptions import TimeoutException

domain="http://blog.nogizaka46.com/"
member="manatsu.akimoto" #メンバーの指定
url=domain+member+"/"

def getImages(soup,cnt,mouthtrue):
    member_path="./"+member
    #画像を保存する関数
    for entry in soup.find_all("div", class_="entrybody"):# 全てのentrybodyを取得
        for img in entry.find_all("img"):# 全てのimgを取得
            cnt +=1
            imgurl=img.attrs["src"]
            imgurlnon=imgurl.replace('https','http')
            if mouthtrue:
                try:
                    urllib.request.urlretrieve(imgurlnon, member_path+ str(year)+'0'+str(mouth) + "-" + str(cnt) + ".jpeg")
                except:
                    print("error",imgurlnon)
            else:
                try:
                    urllib.request.urlretrieve(imgurlnon, member_path + str(year)+str(mouth) + "-" + str(cnt) + ".jpeg")
                except:
                    print("error",imgurlnon)


if(__name__ == "__main__"):
    #保存するブログの始まり
    year=2012
    mouth=12
    #保存するブログの終わり
    endyear=2020
    endmouth=6

    while(True):
        mouthtrue=True
        if mouth<10:
            BlogPageURL=url+"?d="+str(year)+"0"+str(mouth)
        else:
            BlogPageURL=url+"?d="+str(year)+str(mouth)
            mouthtrue=False
        headers = {"User-Agent": "Mozilla/5.0"}
        soup = BeautifulSoup(requests.get(BlogPageURL, headers=headers).content, 'html.parser')#htmlの取得
        print(year,mouth)
        sleep(3)
        cnt = 0
        ht=soup.find_all("div", class_="paginate")
        print("ht",ht)
        getImages(soup,cnt,mouthtrue)#画像保存関数の呼び出し
        if len(ht)>0:#もし同じ月に複数ページあったとき，そのページ分だけ保存
            ht_url=ht[0]
            print(ht_url)
            url_all=ht_url.find_all("a")
            for i,hturl in enumerate(url_all):
                if (i+1)==len(url_all):
                    break
                link = hturl.get("href")
                print("url",url+link)
                soup = BeautifulSoup(requests.get(url+link, headers=headers).content, 'html.parser')
                sleep(3)
                getImages(soup,cnt,mouthtrue)#画像保存関数の呼び出し
        if year==endyear and mouth==endmouth:
            print("Finish")
            sys.exit()#プログラム終了
        if mouth==12:
            mouth=1
            year=year+1
            print("update",year,mouth)
        else:
            mouth=mouth+1
            print("update",year,mouth)

```

ちなみに「#もし同じ月に複数ページあったとき，そのページ分だけ保存」というのは画像で例示すると，こういうイメージです．
<img width="484" alt="スクリーンショット 2020-06-26 15.21.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626852/6980ed98-0edf-504d-5e4b-70927bd84b84.png">
この画像の例でいうと，2013年1月の秋元真夏さんのブログなのですが，1ページ目の画像を保存した後に，2,3,4のリンクを取得して，それぞれのページで画像を保存するという内容になっています．

# 実行結果
試しに秋元真夏さんのブログで実行してみたところ，以下のような形で画像の保存が確認できました．
※2013年1月の画像が欠けているのは，ブログにあげられてた元画像が欠けているためです．
<img width="429" alt="スクリーンショット 2020-06-26 15.31.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626852/27adedba-0f4e-53fe-1883-ce4b0ede2155.png">

ちなみに先ほどのプログラムでhtがわかりにくいかと思ったので，その部分の実行結果を表示します．
少しわかりにくいですが，このようにその月ごとのページをそれぞれスクレイピングで表示しています．
```
ht 
[<div class="paginate"> 1  | <a href="?p=2&amp;d=201301"> 2 </a> | <a href="?p=3&amp;d=201301"> 3 </a> | <a href="?p=4&amp;d=201301"> 4 </a> | <a href="?p=2&amp;d=201301">＞</a></div>, <div class="paginate"> 1  | <a href="?p=2&amp;d=201301"> 2 </a> | <a href="?p=3&amp;d=201301"> 3 </a> | <a href="?p=4&amp;d=201301"> 4 </a> | <a href="?p=2&amp;d=201301">＞</a></div>]
```
その後，以下のように1ページ目をスクレイピングした後に，4ページスクレイピングしていることがわかります．
```
url http://blog.nogizaka46.com/manatsu.akimoto/?p=2&d=201301
url http://blog.nogizaka46.com/manatsu.akimoto/?p=3&d=201301
url http://blog.nogizaka46.com/manatsu.akimoto/?p=4&d=201301
```

# おわりに
余談ですが，井上小百合さんのブログを保存したときは，余裕で数千枚を超えました（余計なものを消去して2385枚でした．）
<img width="750" alt="スクリーンショット 2020-06-26 15.40.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626852/e82ffb83-9ba8-0f27-c030-b903249720c8.png">
さゆの努力家の部分が見えますね．

#参考文献
https://qiita.com/xxPowderxx/items/e9726b8b8a114655d796 の記事がめちゃくちゃ参考になりました・