スクレイピングの学習 Python3系 その4

# 前回の内容
[スクレイピングの学習 Python3系 その3](https://qiita.com/mizssy07/items/f42925894f45d4443bc8)

# 改善点
- seleniumを利用するに当たり、Google Colaboratoryからローカルへ移行
- それに伴い大幅な改修
- 改ページ処理を追加
こちらの記事を大いに参考にした→[【Python】Webスクレイピングチュートリアル -「次へ」ボタンが存在するページをすべて取得する場合 -](https://review-of-my-life.blogspot.com/2017/10/pager-next-selenium.html)

# 手順
- ローカルにpython3系をインストール、バージョンの指定←[こちら](https://hajipro.com/python/mac-python)を参考に
- ローカルで動かすに当たり、エディタを導入(VScode)←[こちら](https://dev.classmethod.jp/tool/python-pyenv-vscode/)を参考に
- 各種モジュールのインストール(pip利用)←[こちら](https://www.python-izm.com/tips/pip/)を参考に
- seleniumのインストール
- Beautiful Soup4のインストール
- pandasのインストール
- requestsのインストール

# 全体のコード
```python:
# coding: UTF-8
from selenium import webdriver
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import pandas as pd
import requests
import datetime
import time

# プログラム上からブラウザを操作する
# webdriverが同ディレクトリにない場合、引数にディレクトリを指定
browser = webdriver.Chrome(
    executable_path="#chromedriverのある場所のパス"
    )

# アクセスするURL = ニュートピ
url = "https://newstopics.jp/"
# ページ推移用のURL指定(相対URLを絶対URLに変換する用)
originalUrl = "https://newstopics.jp/"
browser.get(url)  # ページを開く
page = 1  # ページ数を保存する変数を設定
# データフレームを作成
columns = ["name", "url"]
df = pd.DataFrame(columns=columns)

while True:  # 最終ページまで処理を続ける

    # htmlを取得、BeautifulSoupで扱う
    html = requests.get(url)
    # BeautifulSoupの初期化
    soup = BeautifulSoup(html.content, 'html.parser')
    # 「次へ」を取得
    nextpage = len(soup.find_all("a", {"rel": "next"}))

    if nextpage > 0:
        print("###################page: {} #####################".format(page))
        print("取得中...")

        # aタグの中から、class="title"の含まれたものを取得
        tags = soup.find_all("a", {"class": "title"})

        # 抽出した要素を行列に入れ込む
        for tag in tags:
            name = tag.string  # 記事名の取得
            url = tag.get("href")  # リンクの取得
            se = pd.Series([name, url], columns)  # 行を追加
            df = df.append(se, columns)  # 新規の行を作成

        # 次のページへ移動する
        nextpage_btn = soup.find("a", {"rel": "next"}).get("href")
        btn = urljoin(originalUrl, nextpage_btn)
        print("next url:{}".format(btn))
        browser.get(btn)
        page += 1
        browser.implicitly_wait(10)
        print("次のページへ移動中...")
        url = btn
        time.sleep(10)

    else:  # 次へがない場合に処理を終了
        print("取得完了")
        break

# CSVに出力
# 現在の日付時刻をファイル名に
todaynow = datetime.datetime.now().strftime("%y%m%d%H%M%S")  
filename = todaynow + ".csv"
df.to_csv(filename, index=False, encoding='utf-8')  # encoding指定、おまじない
print("終了!")

# ブラウザを終了する
browser.close()
```

# 詰まったところ
##### chrome web driverの使い方([参考URL](https://qiita.com/motoki1990/items/a59a09c5966ce52128be))
パスを指定しなくても使える方法があるみたいだけど、試しに空欄にしたらエラーが出たので設定。仕様は今後確認。

##### 次ページの取得、移動
参考にした記事とは大きく形を変える必要があった。
次ページの取得は該当の属性を数え、0より大きかったら続行の形に、改ページは一旦hrefの中身を変数に格納する形で解決。

##### 無限ループ
最終ページに行った際の処理を後回しにしてテストしたら無限ループになってしまった。
適度にsys.exit()を挟んでテストをするようにした。

##### スコープの問題
要素の取得をfor文の中でしてしまい、空白のデータが出来た。
for文の外に出して解決。

##### 相対URLの変換
「次へ」のhrefが相対URLだったため、普通に取得してもエラーになってしまった。
`urljoin`を利用して解決。ページ推移用にオリジナルURLを保管する変数を指定した。[参考リンク](href の相対パス詰まり
http://shuzo-kino.hateblo.jp/entry/2016/08/30/221758
)

##### ダウンロードするCSVのファイル名について
重複を避けるため、yymmddhhmmssの形にした。(各二桁の西暦、月、日、時間、分、秒)

# 次回への課題
- ~~CSVでダウンロード~~
- 1時間に1回取得などの動き
- 重複する内容を取得しないようにする
- ~~次ページ以降の取得~~
- 元リンクを取得
- ~~ローカル環境で動かす~~