HtmlAgilityPackは、この種のものに最適です。
実装例:
string pdfLinksUrl = "http://www.google.com/search?q=filetype%3Apdf";
// Load HTML content
var webGet = new HtmlAgilityPack.HtmlWeb();
var doc = webGet.Load(pdfLinksUrl);
// select all <A> nodes from the document using XPath
// (unfortunately we can't select attribute nodes directly as
// it is not yet supported by HAP)
var linkNodes = doc.DocumentNode.SelectNodes("//a[@href]");
// select all href attribute values ending with '.pdf' (case-insensitive)
var pdfUrls = from linkNode in linkNodes
let href = linkNode.Attributes["href"].Value
where href.ToLower().EndsWith(".pdf")
select href;
// write all PDF links to file
System.IO.File.WriteAllLines(@"c:\pdflinks.txt", pdfUrls.ToArray());
ちなみに、HAPのXPath式にはあまり依存しません。いくつかのXPath関数が欠落しており、すべての抽出ロジックをXPath内に配置すると、コードの保守性が低下します。XPath式を使用してかなりの最小値を抽出し、ノードコレクションを反復処理して必要なすべての抽出を実行します(Linqメソッドは非常に役立ちます)。
HAPの真の力は、SGMLドキュメントを解析する機能です。つまり、XHTMLの観点からは無効になる可能性があります(閉じられていないタグ、引用符の欠落など)。