LWPのHTML::Formにinputを追加してPOSTする方法
投稿:2015-12-14
サイトに全自動でアクセスするプログラムをPerlで書く中で、サイトはJavaScriptを使いフォームにinputタグを動的に追加している場所があります。
モジュールHTML::Formはサイトのフォーム処理に便利で使っていますがプログラム側からinputを追加できないので何とかしたい訳です。
# uri_escape_utf8を使います use URI::Escape; # $formが対象のフォーム # 送信ボタンをクリック、ただし、そのリクエストは後で my $req = $form->click(); # フォームにないタグ設定のinputをリクエストに追加 my $add_content; # @append_fieldがフォームにないinput名一覧 # プログラムが設定したいinput/値のセット $spec{input名}=値 for (@append_field) { my $v = uri_escape_utf8($spec{$_}); $add_content .= "&$_=$v"; } $req->add_content($add_content); # バイト数変更をヘッダに反映 $req->header(Content_Length => length $req->content); # リクエスト $res = $self->ua->request($req);
クリックしてリクエストを作成、加工、サイトへリクエストの流れです。
この2番目にある加工が今回の肝になります。
作成したリクエストはHTML::Messageを継承しているのでそちらの参照/変更関数を使って操作できるようになっています。
GETリクエストのURLでよく見かける「&input名=値」という形式でPOSTのデータ(URLじゃないよ)に追加できます。
URLで%を前置するエスケープがあるのでそれをuri_escape_utf8で変換します。
Perlコード、値の両者とも文字コードはUTF-8です。
全部のinputを連結してからリクエストに追加します。
これでサイトへリクエストすると動作します。
ただしヘッダのContent_Lengthが追加前のままですから、送信時に「ヘッダ(Content_Length)と送信するデータサイズが違うからヘッダを修正するね(意訳)」と警告がエラー出力されます。
そこで送信データのバイト数でヘッダを更新して矛盾を解消します。
最後にサイトへリクエストして完了です。
このページを書くにあたり改めて関連リンク先を読むと、
$req->header(Content_Length => length $req->content);は、
$req->content_length(length $req->content);で良いことに気付いた。もうアフターカーニバル(笑)。
LWP::UserAgent - Web ユーザエージェントクラス - perldoc.jp
HTTP::Response - HTTP 形式のレスポンスメッセージ - perldoc.jp
HTTP::Request - HTTP 形式のリクエストメッセージ - perldoc.jp
HTTP::Headers - HTTPメッセージヘッダをカプセル化するクラス - perldoc.jp
HTTP::Message - HTTP 形式のメッセージ (基底クラス) - perldoc.jp
HTML::Form - HTML フォーム要素を表現するクラス - perldoc.jp
URI::Escape - 安全でない文字のエスケープとアンエスケープ - perldoc.jp
HTTP::Response - HTTP 形式のレスポンスメッセージ - perldoc.jp
HTTP::Request - HTTP 形式のリクエストメッセージ - perldoc.jp
HTTP::Headers - HTTPメッセージヘッダをカプセル化するクラス - perldoc.jp
HTTP::Message - HTTP 形式のメッセージ (基底クラス) - perldoc.jp
HTML::Form - HTML フォーム要素を表現するクラス - perldoc.jp
URI::Escape - 安全でない文字のエスケープとアンエスケープ - perldoc.jp