素人がPythonでWebスクレイピングを実装する8

よこのじ(@yokonoji_work)です。

素人がPythonでWebスクレイピングを実装する」の第8回です。第7回ではスクレイピングの対象を絞り込むことができるようになりました。今回は次の機能を実装してプログラム完成とします。

  • ページネーションのページ数分、記事リストを取得する
  • スクレイピングに一定の時間間隔を持たせる
  • 対象URLをスプレッドシートから読み込む
  • スクレイピング結果をスプレッドシートに書き込む

完成版ソースコード

完成したプログラムのソースコードとスプレッドシートの内容です。A2セルのURLを読み込んでから、C2以下のセルに記事タイトルを書き込むようにしています。

python-scraping-8-出力書き込み

ページネーションのページ数分、記事リストを取得する

このシリーズでは記事タイトルの一覧を取得するプログラムを作成してきました。しかし、この単純作業を1ページ分しかできないというのは意味がありません。そのため、ページネーションのページがある分だけ自動でページを移行して、各ページの記事タイトル一覧を取得できるようにします。

python-scraping-8-ページネーション

各ページの記事タイトル一覧の取得の仕組みは次のとおりです。

  • ホーム画面(https://yokonoji.work/)の記事タイトル一覧を取得する
  • 「NEXT」より2ページ目のURLを取得する
  • 2ページ目の記事タイトル一覧を取得する
  • 「NEXT」より3ページ目のURLを取得する
  • 3ページ目の記事タイトル一覧を取得する
  • 「NEXT」より次のページのURLが取得できなくなるまで繰り返す
    (最終ページには「NEXT」が表示されない)

この動作を利用すれば、例えばネットショップから商品情報の一覧を取得することもできます。

スクレイピングに一定の時間間隔を持たせる

スクレイピングするためには、Webページにアクセスする必要があります。そのため、多くのページからデータを取得するために短時間で多くのアクセスを行うと、DoS攻撃とみなされる可能性があります。

サーバーに負荷がかかるとWebサイト表示速度などのパフォーマンスが低下しますので、Webサイト側は規約やrobots.txtというファイルを用いて、人間やクローラーにアクセスの条件を示します。ユーザーはこれらに違反しないように、サーバーに負荷をかけない利用をする必要があります。

「http://www.example.jp/」というURLの場合、「robots.txt」を末尾に付加するとrobots.txtの内容を確認できます。「http://www.example.jp/robots.txt」

  • User-agent: * であれば、すべての種類のクローラーが対象となる
  • Disallow: / であれば、すべてのファイルへのアクセスを許可しない

2つを組み合わせると、すべてのクローラーに対してすべてのファイルへのアクセスを許可しないこととなる。

Wikipedia Robots Exclusion Standard

国立国会図書館法によるインターネット資料の収集について」によると、アクセス間隔を1秒以上空けることが目安として示されています。ただし、1秒に根拠があるわけではないようですので、過剰なアクセスとみなされないように余裕を持った時間間隔の設定が必要です。

時間間隔の設定は、次のように行いました。

import time
time.sleep(2.0)

timeモジュールのsleep関数を使って、別ページにアクセスする前に2秒のスリープ時間を持たせています。

スプレッドシートとの連携

上記の完成プログラムでは、Google Colab上で認証処理を行いますのでこの連携設定は行わなくても大丈夫です。Google Colab以外でプログラムを動作させるときには、連携設定を行った上でスプレッドシートの読み込む必要があります。必要であれば、参考の欄に記載のサイトより、行うべき処理をご確認ください。

下記、連携設定の手順になります。

スプレッドシートからデータを取得して結果を書き込むために、スプレッドシートとの連携の設定を行います。

Google APIsにアクセスして、利用規約に同意します。
https://console.developers.google.com/

次にプロジェクトを作成していきます。

python-scraping-8-新規プロジェクト

今回は「Test project」というプロジェクト名とします。

python-scraping-8-新しいプロジェクト

プロジェクトを作成したら、Google Drive APIを有効にします。Google Drive APIが見つからない場合は、メニューのライブラリから「drive」で検索するとみつかります。

python-scraping-8-driveapi

ライブラリで「sheets」と検索するとGoogle Sheets APIがみつかりますので、こちらも有効にします。

python-scraping-8-sheetsapi

DriveとSheetsの有効化が完了したら、「認証情報を作成」よりサービスアカウントキーを選択します。

python-scraping-8-認証情報

サービスアカウントキーの作成画面にて、役割 > Project > 編集者 を指定します。キーのタイプはそのままJSONで問題ありません。

python-scraping-8-サービスアカウントキー

「作成」を押すと、内容が保存されてjsonファイルがダウンロードされますので、保存しておきましょう。ファイルを開くと“client_email”に続きアドレスが記載されています。このアドレスをスプレッドシートの右上にある「共有」を開いて入力します。

python-scraping-8-アドレス

ペンマークより「編集者」となっていることを確認したら、送信を押して設定は完了です。

対象URLをスプレッドシートから読み込む

Google Colabには初期状態でインストールされていますが、これら2つのライブラリが必要です。

pip install gspread
pip install oauth2client

そして、これらのライブラリをimportします。

import gspread
from oauth2client.client import GoogleCredentials

また、Googleドライブ内のスプレッドシートにアクセスするために認証が必要です。そのための記述がこちらになります。google.colabを使いますので、完成プログラムはそのままではGoogle Colabでないと使えません。

from google.colab import auth

auth.authenticate_user()
gc = gspread.authorize(GoogleCredentials.get_application_default())

あとは次のように対象スプレッドシートのURLを指定して、A2セルからURLを読み込んでRequestsに渡しています。

wks = gc.open_by_url("スプレッドシートのURL").sheet1
url = wks.acell('A2').value

スクレイピング結果をスプレッドシートに書き込む

最後に取得した記事タイトルをスプレッドシートに書き込みます。

update_cell(gyou, retu, a)でスプレッドシートの行と列、書き込む内容を指定します。article_listには取得した記事タイトルの一覧を格納していますので、順に取り出しながら3列(C列)の2行目からひとつずつ下のセルに移動しながら書き込んでいます。

gyou = 2
retu = 3

for a in article_list:
  if len(wks.cell(gyou, retu).value) > 0:
    gyou = gyou + 1
    continue
    
  else:
    wks.update_cell(gyou, retu, a)
    gyou = gyou + 1
    print(a)

なお、セルの指定ミスにより内容が上書きされることを避けるために、if len(wks.cell(gyou, retu).value) > 0で書き込もうとするセルにデータがあれば何も書き込まないようにしています。

 

以上で、スクレイピングプログラム「ローレライ(Loreley)」は完成です。このプログラムをカスタマイズしていけば、いろいろなスクレイピングに対応できそうです。

 

スクレイピングはサイトごとにプログラムの調整が必要ですので、情報がまとまった本が1冊あれば良いかと思います。

素人がPythonでWebスクレイピングを実装する1
素人がPythonでWebスクレイピングを実装する2
素人がPythonでWebスクレイピングを実装する3
素人がPythonでWebスクレイピングを実装する4
素人がPythonでWebスクレイピングを実装する5
素人がPythonでWebスクレイピングを実装する6
素人がPythonでWebスクレイピングを実装する7