curl - URLでデータ通信を行う

スポンサーリンク

curlコマンドはURLでデータ通信を行うことができます。サポートしているプロトコルはHTTP,FTP,SMTP等で、様々な通信に対して利用することができます。ここでは主にHTTPでのWebページ取得方法について紹介します。

curlコマンドの紹介の前に

この記事では、curlコマンドの利用するために、CGIが動作する簡単なWebサーバをローカル環境で構築しています。CGIが動作する簡単なWebサーバはpythonのバージョン2系のCGIHTTPServerモジュールを用いて構築します。

構築方法は単純で

と実行するだけで、カレントディレクトリをドキュメントルートとしてローカル環境に簡単なWebサーバを構築できます。また、3000の数字はポート番号を表しています(ポート番号を省略するとデフォルトでは8000番ポートになります)。

CGIが動作するディレクトリは決められていて、cgi-bin/又はhtbin/の中に存在するファイルがCGIスクリプトとして扱われます。

python3では、http.serverモジュールを用いてWebサーバを構築できます。--cgiオプションを用いると同様にCGIが動作するWebサーバを構築できます。

GETメソッドによるWebページの取得

curlコマンドは、引数にURLを入力することで、GETメソッドでWebページを取得することができます。wgetコマンドと違い、Webページは標準出力されます。そのため、パイプでコマンドを繋げることができ、sedやawk等のコマンドと組み合わせて、結果の出力の編集を行うことが出来ます。

コマンド例

test.html

実行結果

シェルのように'{}'や'[]'を利用することで、複数のWebページを取得することも可能です。また、'{}'や'[]'を用いる場合はシェルに解釈されないように引用符(「' '」や「" "」)で囲います。

取得したWebページをファイルに保存
(-oオプション)

-oオプションを用いることで、取得したWebページを指定したファイルに保存することができます。

出力がファイルやパイプ等のように端末でない場合、curlコマンドは基本的に進捗バーを表示します。

コマンド例と実行結果

また、'{}'や'[]'を用いて、複数のファイルをダウンロードする場合、使用した括弧の数に従って、'#1','#2','#3'...を用いることで、置き換えられる文字列を使用して、ファイルをダウンロードできます。また、'{}'や'[]'を用いる場合はシェルに解釈されないように引用符(「' '」や「" "」)で囲います。

コマンド例と実行結果

GETメソッドによるクエリ文字列の送信

GETメソッドでデータを送信する方法として、URLにクエリ文字列を追加して送信する方法があります。記述方法はhttp://www.example.com/?aaa=testのように、URLの後に'?'を記述し、その後にname=value&name2=value2のように記述することでデータを送信することができます。

curlコマンドでクエリ文字列を記述する場合は、シェルに解釈されないように一部の文字列はエスケープする必要があります。

コマンド例

test.cgi

実行結果

POSTメソッドによるデータの送信

-Xオプションにより、HTTPサーバ(Webサーバ)へのリクエストメソッド(request method)を指定することができます。この-Xオプションを用いて、GETメソッドの他にPOST,PUT,DELETE等のリクエストメソッドを指定することができます。

POSTメソッドはHTMLのフォームのデータ送信、掲示板でのメッセージ投稿処理などに利用されます。

ここでは、例としてCGIプログラムにPOSTメソッドを用います。

コマンド例

test2.cgi

実行結果

CGIプログラムにPOSTメソッドを用いてデータを送信する場合、CGIプログラムは送信されたデータを標準入力として受け取ります。この標準入力は、CONTENT_LENGTHの値を読み取って、データを受け取ります。

Cookieの保存

-cオプションを用いることでWebサイトから送信されるCookieを保存することができます。

Cookieとは、HTTPで状態(state)を保存するために利用されます。状態とは、あるサイトでのログイン状態や言語設定などが挙げられます。

ここでは、CGIプログラムにCookieヘッダーをセットし、それを保存する例を示します。

cookie.cgi

コマンド例と実行結果

Cookieの仕様はRFC 6265 - HTTP State Management Mechanismになります。

Cookieの利用

-bオプションを用いることで、Cookieとしてデータを送信することができます。Cookieとしてデータを送る場合、文字列またはファイルを指定します。

show-cookie.cgi

cookiefile

コマンド例と実行結果

curlコマンドの応用

xmllintコマンドと組み合わせWebスクレイピング

Webスクレイピングとは、ウェブサイトから欲しい情報を抽出することを言います。curlコマンドとxmllintコマンドを組み合わせることでウェブサイトから欲しい情報を抽出することが出来ます。

xmllintコマンドはxmlやhtmlを解析できるコマンドになります。このxmllintコマンドの--htmlオプションと--xpathオプションを用いてHTMLから任意のタグの要素を抽出することが出来ます。XPathの構文仕様はW3CのXPathの仕様に規定されています。

しかし、XPathの構文について、あまり知らなくても、ブラウザから欲しい要素のXPathをコピーすることも出来ます。
例えば、Google Chromeでは情報が欲しい箇所に右クリックを押し、「検証」をクリックすることで、デベロッパーツールを開くことができ、さらにそのデベロッパーツールの画面で欲しい要素に対して、右クリックを押し、「コピー」から「XPathをコピーする」項目があります。ここから簡単にXPathを取得することできます。

xmllintコマンドで要素を抽出することができたら、抽出した文字列を編集していき、欲しい文字列に整形していきます。欲しい文字列に整形するためにはsedやawk等のコマンドを用いることが出来ます。

以下に簡単なWebスクレイピングのパターンの例を示します。

コマンドのパターン例

コマンド例の簡単な解説を行います。

1. 初めにcurlコマンドでWebページの取得を行います。抜き出すテキストが明確ではない場合は何度もサイトにアクセスせずに、まずはこの出力をファイルに出力して

のようにして、練習するべきでしょう。

2.パイプ(|)で繋いでxmllintで取得したい要素を抽出します。これはHTMLのソースと比較しながら行っていきます。xmllintは引数にファイルを指定する必要がありますが、標準入力を指定する場合は、'-'を指定します。また、xmllintでHTMLタグとして解釈されないタグがある場合、エラーメッセージが出力されるため、2>/dev/nullでエラーメッセージを捨てています。

3.抽出した要素を編集するために次のsedコマンドにパイプで渡します。sedコマンドで都合の良いようにテキストを編集します。また、sedコマンドのスクリプトの区切り文字として、's/pattern/replacement/'の形式をよく見ますが、HTMLタグにある'/'と混同しやすいため、's!pattern!replacement!'のように別の区切り文字を使用してもよいでしょう。

4.最後に出力に行番号をつけるためにnlコマンドを用いてます。これはあってもなくてもどちらでもよいでしょう。

ウェブサイトから欲しい情報を抽出するためにcurlコマンドとxmllintコマンドを利用することはとても有用です。しかし、JavaScriptでWebページを動的に作成していくようなサイトの情報を抽出するにはまた別のテクニックが必要になります。具体的にはSeleniumというブラウザの自動操作ツールを用いることで実現できます(Selenium - Web Browser Automation)。

また、Webスクレイピングはcurlコマンドを用いなくても、プログラミング言語を用いたほうが楽な場合も大いにあります。PythonやRubyなどのプログラミング言語の使用を検討してもよいでしょう。

参考

curlの公式サイト
マニュアルとしてはcurl - Manual等が参考に、curlに関わるRFC等の仕様はcurl - Specificationsが参考になります