前回の内容
改善点
- seleniumを利用するに当たり、Google Colaboratoryからローカルへ移行
- それに伴い大幅な改修
- 改ページ処理を追加 こちらの記事を大いに参考にした→【Python】Webスクレイピングチュートリアル -「次へ」ボタンが存在するページをすべて取得する場合 -
手順
- ローカルにpython3系をインストール、バージョンの指定←こちらを参考に
- ローカルで動かすに当たり、エディタを導入(VScode)←こちらを参考に
- 各種モジュールのインストール(pip利用)←こちらを参考に
- seleniumのインストール
- Beautiful Soup4のインストール
- pandasのインストール
- requestsのインストール
全体のコード
# 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)
パスを指定しなくても使える方法があるみたいだけど、試しに空欄にしたらエラーが出たので設定。仕様は今後確認。
次ページの取得、移動
参考にした記事とは大きく形を変える必要があった。
次ページの取得は該当の属性を数え、0より大きかったら続行の形に、改ページは一旦hrefの中身を変数に格納する形で解決。
無限ループ
最終ページに行った際の処理を後回しにしてテストしたら無限ループになってしまった。
適度にsys.exit()を挟んでテストをするようにした。
スコープの問題
要素の取得をfor文の中でしてしまい、空白のデータが出来た。
for文の外に出して解決。
相対URLの変換
「次へ」のhrefが相対URLだったため、普通に取得してもエラーになってしまった。
urljoin
を利用して解決。ページ推移用にオリジナルURLを保管する変数を指定した。参考リンク
ダウンロードするCSVのファイル名について
重複を避けるため、yymmddhhmmssの形にした。(各二桁の西暦、月、日、時間、分、秒)
次回への課題
CSVでダウンロード- 1時間に1回取得などの動き
- 重複する内容を取得しないようにする
次ページ以降の取得- 元リンクを取得
ローカル環境で動かす