python

DPC評価分科会のデータをダウンロードするのが大変なのでPythonを使ってウェブスクレイピングしてみた。BeautifulSoup

厚生労働省はDPC病院に対して退院患者調査を依頼しており、DPCデータの提出に加算を付けて推進しています。その結果をとりまとめて、公開しているのですが(令和元年度DPC導入の影響評価に係る調査「退院患者調査」の結果報告について)、80を超えるファイルに分けられており、いちいちDLするのが大変です。

マーケティングに使用するのに非常に重宝するデータなのですが、ダウンロードさえ大変な状況に対して、ちゃんとテクノロジーを活用して行きましょうと思い、取り組んでみました。

プログラミング言語のPythonを使って、無料で出来てしまいます。

pytonのダウンロードや基本的な使い方についてはこちら↓を参考にしてください

【初学者向け勉強方法】Pythonをはじめてみたいけどどこから手を付けていいかわからない人へ

DPC評価分科会のデータをダウンロードするのが大変なのでPythonを使ってウェブスクレイピングしてみた。BeautifulSoup

おおまかな流れとして、

  1. 必要な関数モジュールのインストール
  2. 必要な関数モジュールのインポート
  3. ダウンロードしたいページのurlを指定
  4. BeautifulSoupの仕様の準備
  5. ダウンロードしたいファイルの大元のurlを記載
  6. リンク先のリストを作成
  7. 出来たリストをエクセルのものだけに限定
  8. ファイル名を付けるために<a>tagをすべて指定
  9. aタグにExcelが含まれている物だけを抽出(本サイトの仕様でエクセルファイルのには必ずExcelの記載があることを利用
  10. 抽出したaタグのテキストだけ取得
  11. イテレータを設定してリストの要素数の分だけエクセルファイルをダウンロード

という手順で進めます。

完成したプログラミングの実演動画

実際どのような感じでダウンロードされるのか実演動画を作って見ましたのでご覧ンください。

必要な関数のインストール

beautifulsoup4をインストールします。

pip install beautifulsoup4

Jupyter notebookで操作している方はpipを!pipのようにはじめに!マークを付けてください。

必要な関数モジュールのインポート

import requests
from bs4 import BeautifulSoup
import urllib.request as req
import urllib
from urllib.parse import urljoin
import re

ダウンロードしたいページのurlを指定

url = "https://www.mhlw.go.jp/stf/shingi2/0000196043_00004.html"

今回はDPC評価分科会の令和元年度のリンク

BeautifulSoupの仕様の準備

res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")
result = soup.select("a[href]")

スクレイピング時によく使うセットなのでこのまま記載しておくと良いと思います。

ダウンロードしたいファイルの大元のurlを記載

base = "https://www.mhlw.go.jp/"

google chromeなどでウェブサイトを開いたときに、右上にある・・・をクリックしてその他のツール→デベロッパーツールを選択すると、html cssの表示が出てきます。その状態でマウスのカーソルを当てると、リンク先が表示されます、そのリンク先のベースとなるurlをこちらに記載します。

リンク先のリストを作成

links = []
for link in result:
    #htmlの参照先を取得
   href = link.get('href')
    #大元のurlとhtml参照先をurljoinで繋げる
    url_1 = urljoin(base, href)
    #リンク先のリストに追加
    links.append(url_1)

linksという空のリストを作成しておき、htmlの参照先を取得、urljoin関数を使って先ほどの大元のurlと今回取得した参照先を結合して、リストに追加します。

出来たリストをエクセルのものだけに限定

出来たリストをエクセルの物だけに限定します。

excels = [s for s in links if s.endswith('xlsx')]

ラムダ式という手法を使って、関数定義をせずに、末尾がxlsxになっている物だけ残す様に書いています。

ファイル名を付けるために<a>tagをすべて指定

ダウンロードするファイルに規則性を持ってファイル名を付ける方が良いので、今回はリンク元の表記をそのままリンク先のエクセルファイルの名前として保存出来る様にしたいと思いました。そこで、soup.find_allメソッドを使ってhtmlのaタグの物だけを指定しています。

all_a=soup.find_all("a")

aタグにExcelが含まれている物だけを抽出(本サイトの仕様でエクセルファイルのには必ずExcelの記載があることを利用

厚生労働省のDPC評価分科会のサイトは丁寧にエクセルファイルへのリンクの最後に必ずExcelの記載がされています。このことを利用して、Excelの表記のあるものに限定して取得しています。わかりやすい様に上でall_aの操作をしていますが、上の操作を省いてこちらを直接実施しても大丈夫です。

このとき、re をインポートしていないとエラーが出ます。reは正規表現を扱うために必要なモジュールです。

excel_a =soup.find_all("a",string=re.compile('Excel'))

抽出したaタグのテキストだけ取得

またまたラムダ式を使ってexcel_aのリストのテキストだけ残しています。

wordlist=[x.text for x in excel_a]

イテレータを設定してリストの要素数の分だけエクセルファイルをダウンロード

ここでは、エクセルファイルのurlとリンク元の表記が1:1で対応したリストが作成出来ているので、イテレータiを設定して、ダウンロードファイルの保存をダウンロード元の表記をファイル名にして保存しています。C:以下はフォルダを何処においているかによって違うので使用する時は各自調整してください。ここではさらにファイル名の先頭に2019と年が入る様にしています。ファイルの先頭に年が入ると、あとで一括してデータベース化する時に便利なのでおすすめです。(どう便利なのかの詳細はそのうちアップしたいと思います。)

for i in range(len(wordlist)):
    urllib.request.urlretrieve(excels[i],'C:/Users/ky/scraping/2019'+wordlist[i]+'.xlsx' )

まとめ

以上、まとめると、以下のようなコードになります。

# -*- coding: utf-8 -*-
#必要な関数のimport
import requests
from bs4 import BeautifulSoup
import urllib.request as req
import urllib
from urllib.parse import urljoin
import re
#ダウンロードしたいurlを指定
url = "https://www.mhlw.go.jp/stf/shingi2/0000196043_00004.html"

#beautiful soup使用の準備
res = req.urlopen(url)
soup = BeautifulSoup(res, "html.parser")
result = soup.select("a[href]")

#ダウンロードしたいファイルの大元のurlを記載
base = "https://www.mhlw.go.jp/"
#リンク先のリストを作成
links = []
for link in result:
    #htmlの参照先を取得
   href = link.get('href')
    #大元のurlとhtml参照先をurljoinで繋げる
    url_1 = urljoin(base, href)
    #リンク先のリストに追加
    links.append(url_1)
#出来たリンク先のリストをエクセルのものだけに限定
excels = [s for s in links if s.endswith('xlsx')]

#ファイル名を付けるためにaタグすべて取得
all_a=soup.find_all("a")

#aタグにExcelが含まれている物だけを抽出(本サイトの仕様でエクセルファイルの<a>には必ずExcelの記載があることを利用
excel_a =soup.find_all("a",string=re.compile('Excel'))
#抽出したaタグのテキストだけ取得
wordlist=[x.text for x in excel_a]

#イテレータを設定してリストの要素数の分だけエクセルファイルをダウンロード。第2引数に保存先とファイル名を記載
for i in range(len(wordlist)):
    urllib.request.urlretrieve(excels[i],'C:/Users/ky/scraping/2019'+wordlist[i]+'.xlsx' )

DPC評価分科会のデータは、DPC病院の立ち位置を見える化するマーケティングに必須のデータだと思っています。良かったら活用してみてください。

他の年度の物も実施したけれどエラーになってしまったという方はこちらの記事もご覧下さい。

【補足記事】DPC評価分科会のデータをダウンロードするのが大変なのでPythonを使ってウェブスクレイピングしてみた。BeautifulSoup