wget

作成日:2005-09-26
最終更新日:

wgetのどこが気に入らないか

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をどのように改造するかを考えたことを載せる。

404の呪い

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 オプションを使う

ソースを変更せずにリンク元を示すために、--debug オプションをつける方法もある。 この場合は大量の情報が出力されるので、気をつけてほしい。


コンパイルのしかた

バージョン 1.12 のコンパイル

私が使っているレンタルサーバは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 である。


バージョン 1.14 のコンパイル

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

バージョン 1.18 のコンパイル

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)

HTML の HEAD 要素の取得

先の章で説明したように、レンタルサーバの 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 になった。

wget の利用法

私が使っているレンタルサーバーでは、次のコマンドを使っている。

/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 オプションを指定すると、何もダウンロードをしない。

debug モード

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 である。

1.認証

--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 情報も調べておく必要がある。

2.ダウンロード

--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 認証

Basic認証のあるページを wget でダウンロードするには、 ユーザー名として --http-user を、パスワードとして --http-passwd を使う。

Basic 認証以外の認証付きサイトのダウンロード

Openpne という、SNS を自前で構築するためのプラットフォームがある。 この入口は、メールアドレスが ID でパスワードが付加されていて、これらが認証情報となっている。 さて、これらの認証情報をわきまえたうえで、SNS の必要な情報をバックアップする(エクスポートする、ダウンロードする、コピーする)には、 どうすればいいだろうか。 いちいち手でダウンロードするのはとんでもないことになる。日記だけで 1 万件を超えるのだ。 wget で認証付きサイトをダウンロードする(webos-goodies.jp)を参考にして、 考えたことを試してみた。いわゆる、クロールに近い。 スクレイピングとも関係がある。

結論から先に言えば、私の場合は、上記サイトで、wget を使った場合、永続的な Cookie による認証の場合でうまくいった。 ただし、いくつか注釈を行う。

cookies.txt は IE のみ

認証情報を wget で得るためには、既存のブラウザでクッキー情報を作成し、それを wget で使える形式の cookies.txt をエクスポートしておく必要がある。 しかし現在、Firefox で Cookie を保存しているのは cookies.sqlite であり、 cookies.txt ではない。 cookies.txt を得たければ Internet Explorer を使うか、Firefox アドオンで Export Cookies という拡張機能を使うしかない。 なお、私は前者の IE を使う方法で対応した。Firefox のアドオンは使っていない。

条件を無視すれば、いくつかの方法が考えられる。

ブラウザのプラグイン

Firefox のプラグイン scarpbook

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 の保存はうまくいくことがわかった。

まりんきょ学問所UNIX 手習い > wget


MARUYAMA Satosi