Requests + BeautifulSoup で html から form データの雛形作成他

Requests と BeautifulSoup は忘れた頃に使って何度も調べるのでメモ。小ネタ。

Requests を使ってログイン処理をするときはだいたいこんな処理をかく。

s = requets.Session()
r = s.get('http://example.com/login')
soup = BeautifulSoup(r.content, 'html.parser')
payload = {
  'id': 'id',
  'password': 'password'
}
s.post('http://example.com/login', data=payload)

payload の部分がこれくらいシンプルならいいけど、csrf token とかをつけて送る場合に BeautifulSoup を使って token 部分を抜き出す必要がある。そんなときはだいたい以下のようなコードを書いて payload の雛形を作る

内包表記ver

payload = {
    input['name']: input['value'] if input.has_attr('value') else ''
    for input in soup.select('form input')
    if input.has_attr('name')
}

for でシンプルに書くとこんな感じ

payload = {}
for input in soup.select('form input'):
    if not input.has_attr('name'):
        continue
    value =  input['value'] if input.has_attr('value') else ''
    payload[input['name']] = value

あとはこの payload に適当に id/pass を詰め込んで post すればよい。

その他メモ

  • BeautifulSoup はdict の ように in を使って要素があるか問い合わせてはダメ('value' in input みたいな)。has_attr を使う。
  • Cookie とか使うなら Session を使う。
  • Session の save / load は pickle でいけそう
import requests, requests.utils, pickle
session = requests.session()
with open('somefile', 'w') as f:
    pickle.dump(session, f)
with open('somefile') as f:
    session = pickle.load(f)
  • findAll ? find_all ? どっちやねん > find_all らしい (最近のpythonのスタイルに従う)

python - beautifulsoup findAll find_all - Stack Overflow