スクレイピングメモ

スクレイピングメモ

requests&BeautifulSoupでフォームデータを送信する際のざっくりとした手順

Seleniumは動作が遅いのでできるだけrequests&BeautifulSoupするのが望ましい。

  1. FirefoxのデベロッパーツールのNetworkタブをみて、どういうリクエストとレスポンスのやりとりをしているか観察(Chromeはリダイレクト元のやりとりがみれないのでFirefoxのほうがいい)。
  2. 必要なフォームデータをBeautifulSoupで集めて、リクエストボディに含めてPOSTする。(クッキー情報はrequests.Session()を使えばよしなにしてくれる)
  3. 失敗したら1に戻る。

フォームデータを集めるコード。

パーサーは基本html.parserを使うけど、世の中HTMLの文法エラーが多い。実験してみるとhtml.parserもある程度は修正してくれるみたいだけど、込み入ったエラーは修正してくれない。html.parserだとエラー部分がざっくりなくなることがある。

html5libはブラウザとおなじように文法エラーを修正しながらパースしてくれるらしい。wordpressの編集画面にも文法エラーがあってかなりはまった…。

requestsでフォームデータ送信する際にUTF-8以外の文字コードを使うには

実験環境

送信したリクエストの中身を確認するには、PHPのビルトインサーバーを使う。ビルトインサーバーを起動して、ルートディレクトリに以下のindex.phpを配置する。

あと、PHPのビルトインサーバーの文字コードはUTF-8のようなので、php.iniに以下の行を追加して文字コードをUTF-8以外にしておく。

UTF-8以外の文字コードでフォームデータ送信

dataオプションに辞書型でフォームデータを与えると、requests.postメソッドが勝手にUTF-8でエンコードしてくれる。手間を省いてくれてありがたいんだが、サーバーがShift-JISなどほかの文字コードを使っている場合は文字化けしてしまう。ちなみにrequests.postメソッドには文字コードを指定するオプションはない。

dataオプションに文字列を与えるとエンコードされないので、以下のようにすればいい。

日本語部分をUTF-8以外の文字コードでパーセントエンコーディングした文字列をつくって、dataオプションに与えている。

ちなみにパーセントエンコーディングしないと以下のような例外が発生する。

ヘッダーにContent-Typeを指定しないとサーバーがフォームデータとして受け取ってくれないので注意(フォームデータにかぎらずなにかしらデータをPOSTする際は、メッセージボディの内容に応じてContent-Typeを設定する必要がある)。

ヘッダーにContent-Typeを指定しないと、$_POSTになにも入ってこない。

ちなみにdataオプションに辞書型で与えた場合はrequests.postがヘッダーも設定してくれる。なにか事情がないかぎり、dataオプションに与えるデータは文字列ではなく辞書型にするべき。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする