【Python】Google ColaboratoryからGoogleドライブにPDFを保存! ~機械学習用データ集めよう~


1. はじめに

こんにちは,HanBeiです。

最近,機械学習にハマっていて勉強をしています。

「機械学習したいけど,どんな実行環境でできるんだい?」
と考えた方もいると思いますが,今回使用するGoogle Colaboratoryや,Jupyter Notebookなど便利なツールがあります。

日々,我々の生活を豊かにしてくださるエンジニアの皆さんには感謝感激です。

1-1. 目的

今回,Google Colaboratoryも用いてスクレイピングをして,Web上に置いてあるPDFデータをGoogleドライブにダウンロードしていこうと思います。

1-2. ターゲット(この記事を読む理由)

Web上にあるPDFデータを用いて,機械学習用のデータを手に入れたい人 の役に立てれば幸いです。

1-3. 注意

スクレイピングは用法・用量を守って正しく守らないと犯罪になります。

「スクレイピングやりたいから,気にせずやっちゃえー!」
と楽観的な人や,心配な人は少なくとも下の2つの記事は目を通すことをオススメします。

miyabisun 様: 「スクレイピングのやり方をQ&Aサイトで質問するな
nezuq 様: 「Webスクレイピングの注意事項一覧

1-4. 確認事項

この記事はスクレイピングの方法を教えておりますが,一切の責任を負いかねます

自分で考え,正しい倫理観をもって使ってください。

2. 準備

2-1. スクレイピングする対象を決める

今回対象とするのが,厚生労働省からCOVID-19について報道発表があったデータです。

新型コロナウイルス感染症の現在の状況と厚生労働省の対応について(令和2年〇月〇日版)というタイトルで,日々更新されています。
このページに国内における都道府県別のPCR検査陽性者数(2020年〇月〇日掲載分 というPDFがあり,これをダウンロードしていきたいと思います。

2-2. Google Colaboratoryを使えるようにする

Google Colaboratoryを使うにあたってGoogleアカウントを作っていない人は,作成しましょう。

ノートブックを新規作成する方法は...
1. Google Colaboratoryをクリックして作業を始める
2. Googleドライブから新規作成する
 参考: shoji9x9 様 「Google Colabの使い方まとめ

3. 実践

3-1. ライブラリーのインポート

from bs4 import BeautifulSoup
import urllib
import urllib.request as req
import time
import requests
import os

3-2. ページを遷移しながら欲しいデータの元へ

欲しいデータが複数ページにわかれているので,その対応をします。

例えば2020年の5月9日のデータが欲しいな~,と思ったら...
「報道発表資料/報道発表資料/新型コロナウイルス感染症の現在の状況と厚生労働省の対応について(令和2年5月9日版)」という階層構造になっているので,遷移する一番初めのページからどんどん潜っていきます。

今回は回りくどい方法で,ページを指定しております。
もっとスマートな方法もあるので,今回はこんな方法もあるんだ程度に参考にしてください。


# urlの格納, prは報道会見の略
pr_url_list = []

# 年月区分の報道発表資料のURL生成
def get_base_url(year,month):
  # ベースとなるURL
  base_url = "https://www.mhlw.go.jp/stf/houdou/houdou_list_" + str(year) + "0" + str(month) + ".html"
  res = req.urlopen(base_url)
  soup = BeautifulSoup(res, "html.parser")

  # 報道発表資料の資料一覧を指定
  all_text = str(soup.find_all('ul', class_= 'm-listNews'))

  # ここで取得したテキストを1行ずつ分割してリストに収納
  all_text_list = all_text.split("\n")

  # リストを1行ずづ読み込んで部分一致する行だけ抽出
  for text in all_text_list:
      if "新型コロナウイルス感染症の現在の状況と厚生労働省の対応について" in text:
        print("行数: " + str(all_text_list.index(text)) + ", url: " + str(text))

        #1行前にあるurlを取り行く
        pr_url = all_text_list[all_text_list.index(text) - 1]
        # 特定箇所を指定してurlにいれる
        date_pr_url = pr_url[26:31]

        PR_URL_LIST = "https://www.mhlw.go.jp/stf/newpage_" + date_pr_url + ".html"

        pr_url_list.append(PR_URL_LIST)
        print(PR_URL_LIST)

  #スクレイピングの1秒ルールを適用
  time.sleep(1)

3-3. 2020年の5月までのURLを取得

スマートな方法がわからないので,1月から5月をfor文で回して見に行っている。


# 5月までを範囲
for month in range(5):
  #1ヵ月ごと追加
  month += 1

  #検索範囲は2020年のみ
  year = 2020

  get_base_url(year, month)

↓ ここまでで実行すると5月分までの指定のURLを確認できる

3-4. PDFのURLを取得

#各月日,都道府県別pdfのurlを格納
date_pt_urls = []
#各月日,都道府県別pdfのurlを格納
pdf_urls_march_april = []

#3,4月分のurlを取得
def march_april_get_pt_url(date_pt):
  date_pt_url = date_pt[19:37]

  PT_PDF_URL = "https://www.mhlw.go.jp/content/" + str(date_pt_url) + ".pdf"
  # print(PT_PDF_URL)

  date_pt_urls.append(PT_PDF_URL)

#5月分のurlを取得(途中で名前変えないでほしい...)
def may_get_pt_url(date_pt):
  date_pt_url = date_pt[19:37]

  PT_PDF_URL = "https://www.mhlw.go.jp/content/" + str(date_pt_url) + ".pdf"
  print(PT_PDF_URL)

  date_pt_urls.append(PT_PDF_URL)
for num in range(len(pr_url_list)):
  print(num)

  #各日ごとのurlを順番に見ていく
  PR_URL = pr_url_list[num]
  res = req.urlopen(PR_URL)
  soup = BeautifulSoup(res, "html.parser")

  all_text = str(soup.find_all)

  #ここで取得したテキストを1行ずつ分割してリストに収納
  all_text_list = all_text.split("\n")

  #リストを1行ずづ読み込んで部分一致する行だけ抽出
  for text in all_text_list:
      if "国内事例における都道府県別の患者報告数" in text:
         march_april_get_pt_url(text)

  #リストを1行ずづ読み込んで部分一致する行だけ抽出
  for text in all_text_list:
      if "国内における都道府県別のPCR検査陽性者数" in text:
         may_get_pt_url(text)      

  #スクレイピングの1秒ルールを適用
  time.sleep(1)

↓ ここまでで実行するとpdfのURLを確認できる

欲しいPDFデータが日によってはないこともあるので,取得したURLがまばらになっている。

3-5. GoogleドライブにPDFをアップロード

#使用したいディレクトリをマウントする
from google.colab import drive
drive.mount('/content/drive')
def download_pdf(url, file_path):
  response = requests.get(url, stream=True)

  #リクエストが成功
  if response.status_code == 200:
    with open(file_path, "wb") as file:
      file.write(response.content)

ダウンロードできるかを確認する。
下記の〇〇〇は自分で作ったフォルダー名と,ファイル名を任意で入れてください。


download_pdf(url=PT_PDF_URL, file_path="drive/My Drive/Colab Notebooks/〇〇〇/〇〇〇.pdf")

3-6. PDFをダウンロード

下記の〇〇〇はファイル名を任意で入れてください。

#データの保存先を指定
google_drive_save_dir = "./drive/My Drive/Colab Notebooks/〇〇〇/pdf"

for index, url in enumerate(date_pt_urls):
  file_name = "{}.pdf".format(index)

  print(file_name)
  pdf_path = os.path.join(google_drive_save_dir, file_name)
  print(pdf_path)

  download_pdf(url=url, file_path=pdf_path)

これで実行すると指定のフォルダにPDFがアップロードされていきます。

4. スクレイピングをやってみて

今回,初めてスクレイピングを試してみましたがなかなか大変でした。

サイトのHTMLが...とか,ダウンロードしたPDFのフォーマットが...

普段はフロントエンドのコードは書きませんが,新たな視点でコードの書き方を検討することができて面白かったです。

ここまでやって結局,機械学習はやるのを止めました。
理由は,欲しいデータが取得できないことに後々気付いたからです(笑)
この計画性のなさ...

なので,この内容を求めている人に見ていただこうと思いった次第です!

ここまで読んでいただいた方,誠にありがとうございます。

ぜひ,コメントやアドバイスをいただけると嬉しいです^^