webページ内の動的iframe内のデータをスクレイピングする方法のメモです。
サンプルwebサイト
河川屋さんにはお馴染みの水文水質データベースより水質・底質のデータをサンプルとしました。
わかりにくいですが、赤枠内がiframeです。
しかもURLは動的に振られる仕様になっています。
スクレイピング(2022/7/4:より簡単な方法を見つけたので修正します)
モジュール
定番のBeautifulSoupを使います。
import pandas as pd from bs4 import BeautifulSoup from urllib import request
手順1:BeautifulSoupで解析
BeautifulSoupでサイトの情報を取得します。
url = 'http://www1.river.go.jp/cgi-bin/DspWquaData.exe?KIND=1&ID=404031284401010&KIJUN=01&BGNDATE=20210101&ENDDATE=20210531&KAWABOU=NO' response = request.urlopen(url) soup = BeautifulSoup(response, features="lxml")
手順2:iframeに移動
iframeを検索してそのページに飛びます。
tmp = soup.findAll("iframe")[0]['src'] url2 = 'http://www1.river.go.jp' + tmp response = request.urlopen(url2)
手順3:スクレイピング
pandasで読み込みます。
dfs = pd.read_html(response.read())
dfs[0]
年月日 | 時分 | 採水位置 | 採水時刻(時分) | 採水位置.1 | 天候 | 水位(m) | 流量(m3/sec) | 全水深(m) | 採水水深(m) | ... | 水温(℃) | 外観(1) | 外観(2) | 外観(3) | 外観(4) | 臭気(冷時) | 透視度(cm) | 透明度(m) | 干潮時刻(時分) | 満潮時刻(時分) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021年02月24日 | 09時00分 | 流心 | 09:00 | 流心 | 晴 | 5.02 | 243.00 | 2.2 | 0.44 | ... | 0.6 | 淡黄色透 | NaN | NaN | NaN | 無臭 | 34 | NaN | NaN | NaN |
1 | 2021年05月19日 | 09時10分 | 流心 | 09:10 | 流心 | 雨 | 6.17 | 187.62 | 3.5 | 0.70 | ... | 15.0 | 無白色濁 | NaN | 濁り多し | NaN | 無臭 | 21 | NaN | NaN | NaN |
修正前の記事
モジュール
定番のseleniumとBeautifulSoupを使います。 chromedriver_binaryのインストール方法は以下を参照。
computational-sediment-hyd.hatenablog.jp
from selenium import webdriver import chromedriver_binary from bs4 import BeautifulSoup import pandas as pd
手順1:selenimで解析
いつもどおり、selenimでChromeを使ってサイトに接続します。
driver = webdriver.Chrome()
url = 'http://www1.river.go.jp/cgi-bin/DspWquaData.exe?KIND=1&ID=404031284401010&KIJUN=01&BGNDATE=20210101&ENDDATE=20210531&KAWABOU=NO'
driver.get(url)
手順2:iframeに移動
iframeを検索してそのページに飛びます。今回はcss_selectorを使いましたが何でもいいです。
- 参考サイト:css_selectorを検索
Python Webスクレイピング テクニック集「取得できない値は無い」JavaScript対応@追記あり6/12 - Qiita
- 参考サイト:iframeへswitch
Seleniumでiframeに出入りしてみた - Qiita
Seleniumでページ内のiframeを操作できない - Qiita
scss = 'body > center > p > iframe'
iframe = driver.find_element_by_css_selector(scss)
driver.switch_to.frame(iframe)
手順3:スクレイピング
ここからはいつもどおりに解析するだけです。 BeautifulSoupとpandasの2手法をまとめておきます。
方法1:BeautifulSoup
BeautifulSoup(driver.page_source, 'html.parser')
<html><head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> <meta content="text/css" http-equiv="Content-Style-Type"/> <title>任意期間水質検索結果</title> </head> <body bgcolor="#ffffff"> <center> <table border="1"> <tbody> <tr> <th bgcolor="#ccffff" nowrap="">年月日</th> <th bgcolor="#ccffff" nowrap="">時分</th> <th bgcolor="#ccffff" nowrap="">採水位置</th> <th align="center" bgcolor="#ccffff" nowrap="">採水時刻<br/>(時分)</th> <th align="center" bgcolor="#ccffff" nowrap="">採水位置<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">天候<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">水位<br/>(m)</th> <th align="center" bgcolor="#ccffff" nowrap="">流量<br/>(m3/sec)</th> <th align="center" bgcolor="#ccffff" nowrap="">全水深<br/>(m)</th> <th align="center" bgcolor="#ccffff" nowrap="">採水水深<br/>(m)</th> <th align="center" bgcolor="#ccffff" nowrap="">気温<br/>(℃)</th> <th align="center" bgcolor="#ccffff" nowrap="">水温<br/>(℃)</th> <th align="center" bgcolor="#ccffff" nowrap="">外観(1)<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">外観(2)<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">外観(3)<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">外観(4)<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">臭気(冷時)<br/> </th> <th align="center" bgcolor="#ccffff" nowrap="">透視度<br/>(cm)</th> <th align="center" bgcolor="#ccffff" nowrap="">透明度<br/>(m)</th> <th align="center" bgcolor="#ccffff" nowrap="">干潮時刻<br/>(時分)</th> <th align="center" bgcolor="#ccffff" nowrap="">満潮時刻<br/>(時分)</th> </tr> <tr> <td align="center" bgcolor="#FFFFCC" nowrap="">2021年02月24日</td> <td align="center" bgcolor="#FFFFCC" nowrap="">09時00分</td> <td align="center" bgcolor="#FFFFCC" nowrap="">流心</td> <td align="center" bgcolor="#FFFFCC" nowrap="">09:00</td> <td align="center" bgcolor="#FFFFCC" nowrap="">流心</td> <td align="center" bgcolor="#FFFFCC" nowrap="">晴</td> <td align="center" bgcolor="#FFFFCC" nowrap="">5.02</td> <td align="center" bgcolor="#FFFFCC" nowrap="">243</td> <td align="center" bgcolor="#FFFFCC" nowrap="">2.2</td> <td align="center" bgcolor="#FFFFCC" nowrap="">0.44</td> <td align="center" bgcolor="#FFFFCC" nowrap="">2.6</td> <td align="center" bgcolor="#FFFFCC" nowrap="">0.6</td> <td align="center" bgcolor="#FFFFCC" nowrap="">淡黄色透</td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap="">無臭</td> <td align="center" bgcolor="#FFFFCC" nowrap="">34</td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> </tr> <tr> <td align="center" bgcolor="#FFFFCC" nowrap="">2021年05月19日</td> <td align="center" bgcolor="#FFFFCC" nowrap="">09時10分</td> <td align="center" bgcolor="#FFFFCC" nowrap="">流心</td> <td align="center" bgcolor="#FFFFCC" nowrap="">09:10</td> <td align="center" bgcolor="#FFFFCC" nowrap="">流心</td> <td align="center" bgcolor="#FFFFCC" nowrap="">雨</td> <td align="center" bgcolor="#FFFFCC" nowrap="">6.17</td> <td align="center" bgcolor="#FFFFCC" nowrap="">187.62</td> <td align="center" bgcolor="#FFFFCC" nowrap="">3.5</td> <td align="center" bgcolor="#FFFFCC" nowrap="">0.7</td> <td align="center" bgcolor="#FFFFCC" nowrap="">16.5</td> <td align="center" bgcolor="#FFFFCC" nowrap="">15</td> <td align="center" bgcolor="#FFFFCC" nowrap="">無白色濁</td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap="">濁り多し</td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap="">無臭</td> <td align="center" bgcolor="#FFFFCC" nowrap="">21</td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> <td align="center" bgcolor="#FFFFCC" nowrap=""> </td> </tr> </tbody> </table> </center> </body></html>
方法2:pandas
dfs = pd.read_html(driver.page_source)
dfs[0]
年月日 | 時分 | 採水位置 | 採水時刻(時分) | 採水位置.1 | 天候 | 水位(m) | 流量(m3/sec) | 全水深(m) | 採水水深(m) | ... | 水温(℃) | 外観(1) | 外観(2) | 外観(3) | 外観(4) | 臭気(冷時) | 透視度(cm) | 透明度(m) | 干潮時刻(時分) | 満潮時刻(時分) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021年02月24日 | 09時00分 | 流心 | 09:00 | 流心 | 晴 | 5.02 | 243.00 | 2.2 | 0.44 | ... | 0.6 | 淡黄色透 | NaN | NaN | NaN | 無臭 | 34 | NaN | NaN | NaN |
1 | 2021年05月19日 | 09時10分 | 流心 | 09:10 | 流心 | 雨 | 6.17 | 187.62 | 3.5 | 0.70 | ... | 15.0 | 無白色濁 | NaN | 濁り多し | NaN | 無臭 | 21 | NaN | NaN | NaN |