webページ内の動的iframe内のデータをスクレイピングする方法のメモです。
サンプルwebサイト
河川屋さんにはお馴染みの水文水質データベースより水質・底質のデータをサンプルとしました。
http://www1.river.go.jp/cgi-bin/DspWquaData.exe?KIND=1&ID=404031284401010&KIJUN=01&BGNDATE=20210101&ENDDATE=20210531&KAWABOU=NO
わかりにくいですが、赤枠内が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)
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を使いましたが何でもいいです。
Python Webスクレイピング テクニック集「取得できない値は無い」JavaScript対応@追記あり6/12 - Qiita
Seleniumでiframeに出入りしてみた - Qiita
Seleniumでページ内のiframeを操作できない - Qiita
scss = 'body > center > p > iframe'
iframe = driver.find_element_by_css_selector(scss)
driver.switch_to.frame(iframe)
ここからはいつもどおりに解析するだけです。
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 |