wget |
作成日:2005-09-26 最終更新日: |
wgetは、httpを利用して、 インターネット上のファイルをローカルコンピュータに保存するソフトだ。 よくできたソフトだと感嘆する。 UNIX ならば http://ftp.gnu.org/gnu/wget/ からダウンロードしてコンパイルすればよい。 最新版は 2013 年 10 月現在 1.14 、2014 年 6 月現在では 1.15 のようだ。 2016 年 12 現在は 1.18 になっている。
Windows 版は、gnuwin32.sourceforge.net にもあるがバージョンが古めである。 下記ページからのほうが、最新のバージョンがダウンロードできる可能性が高い。
http://eternallybored.org/misc/wget/
さて、wget を自分なりに改良したいと思うこともある。 このページは、wgetをどのように改造するかを考えたことを載せる。
wgetの機能はいろいろあるが、今回話題にするのは表示である。 あるファイルをダウンロードするとき、表示も一緒に行われる。 典型的な表示は次の通りである。
--21:41:18-- http://www.ne.jp/asahi/music/marinkyo/index.html.eo
=> `www.ne.jp/asahi/music/marinkyo/index.html.eo'
www.ne.jp:80 への接続を再利用します。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 2,218 (2.2K) [text/html]
0K .. 100% 1.78 MB/s
21:41:18 (1.78 MB/s) - `www.ne.jp/asahi/music/marinkyo/index.html.eo' を保存しました [2218/2218]
一方、リンクがあるのに見つからない場合は、404 Not Found エラーが出てしまう。
--21:41:22-- http://www.ne.jp/asahi/music/marinkyo/taglibroj/vortaro.html.ja
=> `www.ne.jp/asahi/music/marinkyo/taglibroj/vortaro.html.ja'
www.ne.jp:80 への接続を再利用します。
HTTP による接続要求を送信しました、応答を待っています... 404 Not Found
21:41:22 エラー 404: Not Found。
問題は、このつながらないリンクが、どのファイルに書かれているかを探すことだ。 このメッセージからは、どのファイルに書かれているかはわからない。 そこで、どのファイルからのリンクかを正常、エラーを問わず、表示させたい。
では、どこをどう直せばいいか。 イメージの一例を次に示す。
--21:41:18-- http://www.ne.jp/asahi/music/marinkyo/index.html.eo
=> `www.ne.jp/asahi/music/marinkyo/index.html.eo'
<= `www.ne.jp/asahi/music/marinkyo/index.html.ja'
www.ne.jp:80 への接続を再利用します。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 2,218 (2.2K) [text/html]
0K .. 100% 1.78 MB/s
21:41:18 (1.78 MB/s) - `www.ne.jp/asahi/music/marinkyo/index.html.eo' を保存しました [2218/2218]
ではソースコードで、=>が出ている箇所を探す。
% grep '=>' *.c(前略) http.c: logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n", (後略)
これは、1073行と1074行の変更になる。 なお、現在はバージョンが変わっているので別の行になっているはずだ。
logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n <= '%s'\n",
tms, hurl, tmp, locf, referer);
さて、結果はどうだったか。
--22:46:40-- http://www.ne.jp/asahi/music/marinkyo/taglibroj/vortaro.html.ja
=> `www.ne.jp/asahi/music/marinkyo/taglibroj/vortaro.html.ja'
<= 'http://www.ne.jp/asahi/music/marinkyo/taglibroj/hodiaux.html.ja'
www.ne.jp:80 への接続を再利用します。
HTTP による接続要求を送信しました、応答を待っています... 404 Not Found
22:46:40 エラー 404: Not Found。
思った通り、リンク元も表示されるようになった。
なお、この変更により、最初に指定したファイルはどのように表示されるかが問題となる。
--22:46:36-- http://www.ne.jp/asahi/music/marinkyo/index.html.ja
=> `www.ne.jp/asahi/music/marinkyo/index.html.ja'
<= '(null)'
www.ne.jp をDNSに問いあわせています... 202.224.39.35
www.ne.jp|202.224.39.35|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 6,393 (6.2K) [text/html]
0K ...... 100% 92.38 MB/s
22:46:37 (92.38 MB/s) - `www.ne.jp/asahi/music/marinkyo/index.html.ja' を保存しました [6393/6393]
NULL をそのまま表示してしまうのはまずいと思うが、いい方法が見付からない。 (2005-09-26)
ソースを変更せずにリンク元を示すために、--debug オプションをつける方法もある。 この場合は大量の情報が出力されるので、気をつけてほしい。
私が使っているレンタルサーバは2つある。1つは wget が標準で備えられているが、 もう一つは備えられていない。仕方なく自分でインストールした。 wget のソースを展開したディレクトリで、次のコマンドを入力する。
% ./configure --prefix=$HOME/local --with-libintl-prefix=/usr/local -with-libiconv-prefix=/usr/local % make % make install
./configure で2つの --with で始まるオプションを忘れてしまうと、多言語対応ができないことがわかった。 このときインストールした wget のバージョンは 1.12 である。
2013 年、wget の最新版は 1.14 である。これを上記の手順でインストールしようとしたが、 このようなエラーが出た。
configure: error: --with-ssl was given, but GNUTLS is not available.
1.13 からは ssl のライブラリとして GNUTLS をデフォルトで使うようになったが、 そのライブラリがないといっている。GNUTLS を使うのはあきらめ、弱く OpenSSL を使うことにした。
% ./configure --prefix=$HOME/local --with-libintl-prefix=/usr/local -with-libiconv-prefix=/usr/local --with-ssl=openssl % make % make install
2016 年、バージョン 1.18 を Vine Linux 6.3 でコンパイルしようとしたが、次のエラーが出た。
$ ./configure (中略) $ make (中略) gnutls.c:41:29: error: gnutls/abstract.h: No such file or directory gnutls.c: In function 'pkp_pin_peer_pubkey': gnutls.c:703: error: 'gnutls_pubkey_t' undeclared (first use in this function) gnutls.c:703: error: (Each undeclared identifier is reported only once gnutls.c:703: error: for each function it appears in.) gnutls.c:703: error: expected ';' before 'key' gnutls.c:717: error: 'key' undeclared (first use in this function) make[3]: *** [gnutls.o] Error 1
検索してみると、 https://lists.gnu.org/archive/html/bug-wget/2016-05/msg00000.html で、次の回答がある。
> It looks like it isn't > compatible with older versions of GnuTLS. > > Is it possible for you to update to libgnutls28 (plus -dev package) ?では、私の Vine Linux ではどうなっているか。 /usr/lib/libgnutls.so.26 である。つまり、古いためにコンパイルできない。 Vine には新しいものはないので、ここで引き下がろう。(2016-12-17)
先の章で説明したように、レンタルサーバの wget は、 備え付けのものと自力でインストールしたものとの2種類がある。 自力でインストールした wget のバージョンは 1.12 だが、 備え付けの wget のバージョンは 1.10.2 だ。
さて、この両者には違いがあるようだ。1.10.2 では、HEAD 要素に記述されているリンクを取得するが、
1.12 では取得しない。HEAD 要素に記述されているリンクとは、
たとえば、<head> と </head> に囲まれた個所にあるLINK要素
<link rel="top" href="../index.html.ja" />
で示される href のリンク先のことである。
たとえば、$HOMEPAGE/faure/barkaroloj.html.eo のページでは、 HEAD 要素に次のように記述している。
<link rel="alternate" lang="en" title="angla" href="./barkaroloj.html.en" />
ところが、上記のリンク先である barkaroloj.html.en がダウンロードされていない。 wget 英語のバージョン情報を見たがわからない。まず、実験することにした。
% wget -i http://www.ne.jp/asahi/music/marinkyo/faure/barkaroloj.html.eo % ls (前略) barkaroloj.html.en (後略)
このようにダウンロードはできている。 従って、問題は私が使っている wget のコマンドオプションにあったか、他の問題と思われる。
その後、備え付けの wget バージョンも 1.12 になった。
私が使っているレンタルサーバーでは、次のコマンドを使っている。
/usr/local/bin/wget -m -A "*.??" -R js -np http://www.ne.jp/asahi/music/marinkyo/index.html.ja
-m : mirror を表す。
-A : 受け入れを許す拡張子を表す。
-R : 受け入れを拒む拡張子を表す。
-np: 親ディレクトリには上らない。
これに合わせて --spider オプションを指定すると、何もダウンロードをしない。
wget にデバッグモード --debug のオプションを付けると、 一つのページに長い情報を出してくれる。こんな感じだ。
--2013-11-17 22:08:46-- http://www.ne.jp/asahi/music/marinkyo/prezento/sercxilo.html.ja Reusing existing connection to www.ne.jp:80. Reusing fd 3. ---request begin--- HEAD /asahi/music/marinkyo/prezento/sercxilo.html.ja HTTP/1.0 Referer: http://www.ne.jp/asahi/music/marinkyo/index.html.ja User-Agent: Wget/1.12 (freebsd8.1) Accept: */* Host: www.ne.jp Connection: Keep-Alive ---request end--- HTTP request sent, awaiting response... ---response begin--- HTTP/1.1 200 OK Date: Sun, 17 Nov 2013 13:08:46 GMT Server: Apache/2.2.16 (Debian) Content-Location: sercxilo.html.ja.utf8 Vary: negotiate TCN: choice Last-Modified: Wed, 02 Oct 2013 13:03:59 GMT ETag: "4d3833-2626-4e7c1b3e7026d;4e7c1b3df51c9" Accept-Ranges: bytes Content-Length: 9766 Keep-Alive: timeout=5, max=93 Connection: Keep-Alive Content-Type: text/html; charset=utf-8 Content-Language: ja ---response end--- 200 OK URI content encoding = `utf-8' Length: 9766 (9.5K) [text/html] Remote file exists and could contain links to other resources -- retrieving.
ここで確認してもらいたいのは、--request begin-- で始まる区画だ。 HEAD の行のあとに Referer: がある。これは、HEAD 行にあるページは、 Referer: にあるページから参照されている、ということを表している。 したがって、wget で参照していたが見つからなかったページが、 どのページで参照されているかを調べることができる。
実際には、wget を --debug モードつきで動作させて、 標準エラー出力から得られたデータを egrep "^HEAD|^Referer" でパイプ出力させればよい。
ベーシック認証以外に、自前のフォームで認証を行うシステムがある。 このようなシステムで Wget によるダウンロードを行うにはどうすればよいか。 もっか調査中である。
以下、wgetの使い方:認証してFORMを送信するようなページでダウンロードする [コンピュータ] (shigekun.blog.so-net) の内容に即して記述する。なお、これからの私の実験は、Windows の wget 1.15 built on mingw32 である。
--keep-session-cookies、 --save-cookies、 --post-dataを付けて、認証させクッキーをファイルに保存しておく
wget \
--keep-session-cookies \
--save-cookies=cookies.txt \
--post-data 'POSTするデータ(UserId=...&Password=...)' \
ログインページのPOST先URL
ログインページの POST 先 URL や POST する情報は、ページのソースを見て調べる。 しかし、この方法では、POST する情報を決めづらい。また、hidden 情報も調べておく必要がある。
--load-cookies、--post-data、-Oを付けてダウンロードする。
wget \
--referer=リファラ(ダウンロードページのURL) \
--load-cookies cookies.txt \
--post-data 'POSTするデータ(key1=value1&key2=value2...)' \
-O 保存するファイル名 \
ダウンロードページのPOST先のURL
リファラは必要に応じて付加する。
ユーザーエージェント(User-Agent)は設定できる。--user-agent を使う。
ユーザーエージェントを設定するする理由は以下のとおりである。 ブラウザそしてより拡大した概念であるユーザーエージェントは、WEB サーバーに接続するときに 自分のブラウザなりユーザーエージェントなり名前やバージョンを伝える。この名前は正確な名前であるべきだ。 ところが、サーバーの設定によって、「見ていいのはこのブラウザだけだ」と勝手に決め付け、 決めたブラウザ以外を排除していることがある。これは問題である。 この問題を避けるために、見ていいブラウザのふりをするために、 仕方なく使うものである。
Basic認証のあるページを wget でダウンロードするには、 ユーザー名として --http-user を、パスワードとして --http-passwd を使う。
Openpne という、SNS を自前で構築するためのプラットフォームがある。 この入口は、メールアドレスが ID でパスワードが付加されていて、これらが認証情報となっている。 さて、これらの認証情報をわきまえたうえで、SNS の必要な情報をバックアップする(エクスポートする、ダウンロードする、コピーする)には、 どうすればいいだろうか。 いちいち手でダウンロードするのはとんでもないことになる。日記だけで 1 万件を超えるのだ。 wget で認証付きサイトをダウンロードする(webos-goodies.jp)を参考にして、 考えたことを試してみた。いわゆる、クロールに近い。 スクレイピングとも関係がある。
結論から先に言えば、私の場合は、上記サイトで、wget を使った場合、永続的な Cookie による認証の場合でうまくいった。 ただし、いくつか注釈を行う。
認証情報を wget で得るためには、既存のブラウザでクッキー情報を作成し、それを wget で使える形式の cookies.txt をエクスポートしておく必要がある。 しかし現在、Firefox で Cookie を保存しているのは cookies.sqlite であり、 cookies.txt ではない。 cookies.txt を得たければ Internet Explorer を使うか、Firefox アドオンで Export Cookies という拡張機能を使うしかない。 なお、私は前者の IE を使う方法で対応した。Firefox のアドオンは使っていない。
条件を無視すれば、いくつかの方法が考えられる。
Firefox のプラグイン scrapbook は、今見ている該当ページはもちろん、そのページからたどっていけるリンクの情報まで保存することができる。 まず、Mixi で試してみた。欲しいのは、自分が書いた日記だけである。 なお、Mixi では、自分の書いた日記は、http://mixi.jp/view_diary.pl?id=(記事のID番号)&owner_id=(自分のID番号) で表示されることに注意する。 のちのために、この自分のID番号を控えておく。これは 7 桁の数字のはずである。
このプラグインを導入すると、プルダウンメニューに Scrapbook(C) が新たにできる。 ここをプルダウンすると[ページを詳細に保存...]というメニューがあるのでここを選ぶ。 すると、次の <ScrapBook - 保存の詳細>というダイアログウインドウが出てくる。左側のタブが表示されているが、 右側の[コメント]タブへいけば、任意のコメントを書くことができる。 左側のタブに戻ると、 一番下に掘り下げ保存の欄があり、リンクをたどる深さが 0 1 2 3 と出ている。0 を選べば該当ページだけだが、 1 を選ぶと該当ページにリンクしているページまで取り込むことができる。1 を選んで[取り込む]ボタンをクリックすると、 <保存 - ScrapBook>というダイアログウィンドウが出てくる。ここですぐに[一時停止]をクリックする。 これは、保存するファイルを選ぶためだ。
さて、この状態でほしいページは自分の日記だけであるから、[フィルタ]ボタンを選んで[文字列でフィルタ...]を選び、 1 行のテキスト欄にさきほど控えた7桁の数字を入力し、[OK]ボタンをクリックする。 すると、チェックされたファイルが減ったことがわかるだろう。この状態で[開始]ボタンをクリックすれば、保存が始まる。
保存が終わった後のページは、フォルダ
C:\Users\Windowsのログオン名\AppData\Roaming\Mozilla\Firefox\Profiles\固有のディレクトリ名\ScrapBook\data\YYYYMMDDhhmmss
に保管されている。私の場合、次の通りだった。
favicon.ico はファビコンである(_001がついているのも同じ)。index.dat はこの ScrapBook で保存したときの情報である。 ここの comment 行は、ダイアログウィンドウでコメントを入力した場合に残る。 index.html は該当ページそのもの。複数あるのは、他のページを見た後、該当ページに戻ったときのページを律儀に保存している (と思うがよくわからない)。 list_wall.html は伝言板へのリンク。 sb-file2url.txt は、このScrapBook で保存したファイル名とURL の関係が書かれたファイルである。。 sb-url2name.txt は、URL のタイトル名。 show_diary_picture.htmlは、日記の画像表示であろうが、よくわからない。 show_profile.htmlは自己紹介。 sitemap.xml は、サイトマップを XML 形式で表現したファイル。 そして、view_diary.html 関係が日記の内容である。
以上で、mixi の保存はうまくいくことがわかった。