LoginSignup
3
3

More than 5 years have passed since last update.

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

Posted at

前回の内容

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

改善点

手順

  • ローカルに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回取得などの動き
  • 重複する内容を取得しないようにする
  • 次ページ以降の取得
  • 元リンクを取得
  • ローカル環境で動かす
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3