読者です 読者をやめる 読者になる 読者になる

DirtyなHTMLなのにXHTMLと名乗っているページをC#でスクレイピングする

C# HTML

C#でスクレイピング - DENKENを参考にやってみた。

元ネタはGoogleが吐いたHTMLを処理してたので(比較的キレイなHTMLなんだろう)、HTMLtoXHTMLは無事にXHTMLに変換できていたが、とある有名なブログのページを変換しようとしたら、XHTMLの宣言部が下記のように見事に壊れて、XDocument.Parse(xhtml)でXmlExceptionで落ちる。

<?xml version="1.0" encoding="Shift_JIS"="="  ?>
<!DOCTYPE html="html" PUBLIC="PUBLIC" -="-"  xmlns="http://www.w3.org/1999/xhtml"  />
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" xmlns:xml="urn:xml" >

XHTMLの宣言部を削って変換を掛けたらうまくいった。

// original: http://d.hatena.ne.jp/uesama99/20080219/1203394007

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using HTML2XHTMLLib;
using System.Net;
using System.IO;

namespace ScrapingSample
{
    class Program
    {
        static void Main(string[] args)
        {
            WebClient wc = new WebClient();
            string html = wc.DownloadString("http://someblog.com/somepage.html");

            html = html.Replace("<?xml version=\"1.0\" encoding=\"Shift_JIS\"?>", "");
            html = html.Replace("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">", "");
            html = html.Replace("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"ja\" lang=\"ja\">", "<html>");

            XHTMLUtilities util = new XHTMLUtilities();
            string xhtml = util.convertToXHTML(html);

            const string XHTML = "{http://www.w3.org/1999/xhtml}";

            XDocument xdoc = XDocument.Parse(xhtml);
            var query = from a in xdoc.Descendants(XHTML + "a")
                        where a.Attributes("class").FirstOrDefault(atr => atr.Value == "l") != null
                        select a;

            foreach (var item in query)
            {
                Console.WriteLine("Title={0}", item.Value);
            }

            Console.WriteLine("完了しました。");
            Console.Read();

        }
    }
}

XHTMLじゃないのにXHTML宣言をするのは有害」だと、どこかのページで見たが、ここでもそれが見事に当てはまってる。

LINQのお勉強しなきゃw