|
C# Tips |
|
No.0002 HTMLに含まれる画像を取得 |
この例のコンソールアプリケーションは引数に指定したHTMLファイルへのURLを開いて、
そのHTMLファイルに含まれている画像ファイル(*.jpg; *.gif; *.png)すべてをローカルディスクのカレントディレクトリにダウンロードして保存します。
ただし、2重ダウンロードのチェックは行っていないので、HTML中に同じファイルへの参照があった場合は再度ダウンロードされ、既存のファイルに上書きして保存します。
また、ディレクトリ構造はすべて取り除いてローカルディスクにダウンロードするので、
たとえば「path001/myimage.jpg」,「path002/myimage.jpg」のようにパスが違って名前が同じファイルがあった場合、HTML中で後に現れる「myimage.jpg」で上書きされてしまいます。
(これを解決する簡単な方法としてパスも含めてファイル名にするという方法が考えられます。たとえば「path001_myimage.jpg」「path002_myimage.jpg」といった感じで。)
|
using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
namespace prismbox.sample.httpclient {
class Class2 {
static void Main(string[] args) {
string baseurl = "";
if (args.Length != 1) {
Console.WriteLine("引数にURLを指定してください");
return;
} else if (!args[0].ToLower().StartsWith("http://")) {
Console.WriteLine("URLは「http://」で始まっている必要があります");
return;
} else {
if ((args[0].ToLower().StartsWith("http://")) && (args[0].Length == 7)) {
Console.WriteLine("引数にURLを指定してください");
return;
}
}
int pos = args[0].LastIndexOf("/");
if ((args[0].ToLower().StartsWith("http://")) && (pos == 6)) {
baseurl = args[0] + "/";
} else {
baseurl = args[0].Substring(0, pos + 1);
}
try {
WebClient wc = new WebClient();
Stream st = wc.OpenRead(args[0]);
StreamReader sr = new StreamReader(st);
String strHtml = sr.ReadToEnd();
sr.Close();
st.Close();
Regex rSRC = new Regex("src\\s*=\\s*(?:\"(?<1>[^\"]*)\"|(?<1>\\S+))",
RegexOptions.IgnoreCase|RegexOptions.Compiled);
Match mSRC;
for (mSRC = rSRC.Match(strHtml); mSRC.Success; mSRC = mSRC.NextMatch()) {
string val = mSRC.Groups[1].Value;
if (val.ToLower().EndsWith(".jpg") || val.ToLower().EndsWith(".gif") ||
val.ToLower().EndsWith(".png")) {
Console.Write("Downloading " + val + " ... ");
string lcfile = val;
if (val.IndexOf("/") != -1) {
lcfile = val.Substring(val.LastIndexOf("/") + 1);
}
if (!val.ToLower().StartsWith("http://")) {
wc.BaseAddress = baseurl;
} else {
wc.BaseAddress = "";
}
wc.DownloadFile(val, lcfile);
Console.WriteLine("OK");
}
}
} catch (Exception e) {
Console.WriteLine("エラーが発生しました\r\n\r\n" + e.ToString());
}
return;
}
}
}
|
|
No.0001のソースコードよりきちんと引数チェックをしてみました。ただ、HTTPには「https://」というSSL越しのものもあるのですが、この例ではそれは無視しています。
最初はHTML中から「<img src=」を探して画像ファイルを見つけようと思いましたが、「img」の直後に「alt」とか「width」等がくることも考えられるので、
「src=」のみを探すようにしています。この「src=」の検索には正規表現を用いています。
Regexのコンストラクタでは「src=""」の「""」の中身だけ取得できるようにグループ化構造体を用いて正規表現を記述しています。
そして拾ったファイル名に拡張子「.jpg」「.gif」「.png」が付いているかチェックします。ここで拡張子を調べている理由は「src」はJavaScript等の外部ファイルを参照するときにも使われるからです。
多少横着ですが「.jpg」「.gif」「.png」に固定することでまず間違いなく「img」の「src」が拾えます。(ただしこうすることでCGIが自動生成する「.cgi」の拡張子が付いた画像ファイルは拾えないということになりますが...)
実行はコマンドプロンプトより次のようにして行います。(例のソースはそのまま「csc」でコンパイルすれば動きます。実行ファイル名は「httpclient.exe」とします)
|
C:\samples>httpclient.exe http://www.hogehoge.com/foo/
|
|
これで「http://www.hogehoge.com/foo/」のデフォルトHTML(index.htmlやDefault.htm等)に含まれる画像ファイルはすべて「c:\samples」にダウンロードされます。
もちろんURLは「http://www.hogehoge.com/foo/sample.html」のようにファイル名を直接指定してもいいです。すると「sample.html」に含まれる画像ファイルがダウンロードされます。
注意する点は「http://www.hogehoge.com/foo/sample」を指定した場合、「sample」というHTMLファイルを開こうとするということです。
「sample」ディレクトリを参照させたい場合は「http://www.hogehoge.com/foo/sample/」と最後に「/」を忘れずに付加する必要があります。
|
|
|
|