.rute1/

キャリア/心理学/読書/Pythonなどなど

【Python】requestsでボタンを擬似クリック

requestsでボタンを擬似クリック

Beautiful Soupでhrefが取得できないボタン等のクリック動作をrequestsで再現する方法を調べたので、まとめます。

hrefが取得できないボタン

例えばこのページの「CSVダウンロード」ボタン部分などはBeatiful Soupでもhrefが取得しにくいためにrequestsでのスクレイピングが困難です。
CSVダウンロード f:id:rutei:20181130205349p:plain

csvダウンロード」ボタンのソースコードはこのようになっています。

<input class="btn btn-primary" type="submit" value="CSVダウンロード">

おそらくこのボタンを押すとなんらかのscriptが動いてダウンロードが始まるものと思います。
requestsでこのボタンをクリックするという動作を再現することはできないので、seleniumを使うといった選択肢をとることが多いかもしれませんが、場合によってはrequestsだけでボタンをクリックしたのと同等の通信を再現することができます。
以下がその方法です。

crhomeデベロッパーツールでnetworkを見てみる

f:id:rutei:20181130205413p:plain

デベロッパーツールを表示した状態でボタンをクリックすると、networkタブでどのような通信が行われているか確認することができます。
今回のダウンロードもバッチリURLを確認することができました。
URLはhttps://www.itdashboard.go.jp/Csv/downloadで、ここにPOSTでdataを送れば良さそうです。
cookieなどはrequestsのsession()を使えば処理してもらえます。
POSTで送るdataもデベレッパーツールから確認できます。
f:id:rutei:20181130205424p:plain

最終的なコードはこのようになりました。

import requests

# ページにアクセス
session = requests.Session()
res = session.get('https://www.itdashboard.go.jp/DataFeeds/csv')
res.raise_for_status() # エラーならここで例外を発生させる

# dataに項目をセット
data = {
    "_method": "POST",
    "year": "",
    "modelname": "BasicInformationAll"
}

# クリック時の通信
res = session.post('https://www.itdashboard.go.jp/Csv/download', data=data)
res.raise_for_status() # エラーならここで例外を発生させる

# レスポンスで返ってきたコンテンツをcsvとして保存
contentType = res.headers['Content-Type']
contentDisposition = res.headers['Content-Disposition']
ATTRIBUTE = 'filename='
fileName = contentDisposition[contentDisposition.find(ATTRIBUTE) + len(ATTRIBUTE):]

with open(fileName, 'wb') as saveFile:
        saveFile.write(res.content)

ファイルを保存する部分はこちらの記事を参考にしました。
Pythonのrequestsを利用してファイルダウンロードする方法 - Qiita