スクレイピングメモ

スクレイピングメモ

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以外の文字コードでパーセントエンコーディングするには

requestsを使って、文字コードがshift-jisのサーバーと通信する実験を行う。

実験環境

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

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

まずはデフォルトのutf-8でフォームデータ送信

日本語が文字化けしてしまう。requests.postメソッドがutf-8でパーセントエンコードしているのだが、サーバーがShift-jisで解釈しようとしたからだ。

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

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

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

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

文字列にせずに辞書型のままrequests.postメソッドに与えると、パーセントエンコーディングしたものをさらにパーセントエンコーディングしてしまう。%が%25にエンコードされしまい、name:%93%87%93c となってしまう。

ちなみにクライアント側がshift-jisをデコードできるのはヘッダーに「’Content-type’: ‘text/html; charset=Shift_JIS’」が入ってくるため。

また、4行目でパーセントエンコーディングしないと以下のような例外が発生する。

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

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

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

スクレイピングするメリット

単に便利、というだけではない。いろいろなサイトを攻略しようとするなかで、サイトのつくりかたの勉強になる。たとえば、なるほど画像をダウンロードされないようにcanvas要素に描いてるんだぁとか発見がある。自分のサイトづくりにも活かせる。

シェアする

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

フォローする