Пример #1
0
        static void Main(string[] args)
        {
            var cancelSource        = new CancellationTokenSource();
            CancellationToken token = cancelSource.Token;

            Task job = Task.Factory.StartNew(() =>
            {
                using (var web = new WebClient()
                {
                    Encoding = Encoding.UTF8
                })
                {
                    token.Register(() => {
                        web.CancelAsync();
                    });
                    int count = 0;
                    var html  = web.DownloadString("http://livetube.cc/ユーザー/タイトル");

                    // ストリームのURLを取得
                    Match m       = new Regex("var comment_entry_id = \"([^\"]*)\";").Match(html);
                    var stream_id = "";
                    if (m.Success && (m.Groups.Count > 1))
                    {
                        stream_id = m.Groups[1].Value;
                    }

                    // HTMLのパースにXMLパーサーを使う
                    // XMLの文字実体参照は5つしかないのでXHTMLとしてパースする
                    // ただしW3Cにアクセスしにいくと迷惑なのでDTDをここからダウンロードして保存しておく
                    // www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd
                    FileInfo dtdFile = new FileInfo("xhtml11-flat.dtd");
                    Uri dtdPublicUri = new Uri("http://www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd");
                    var xpr          = new DummyXmlResolver();
                    using (FileStream fs = dtdFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xpr.Add(dtdPublicUri, fs);
                    }

                    var nameRegex = new Regex("^\\s*\\d+\\s:\\s*(.*)\\s$");
                    try
                    {
                        while (true)
                        {
                            // 必要なコメントをダウンロードする(中身はHTML要素)
                            var url = String.Format("http://livetube.cc/stream/{0}.comments.{1}", stream_id, count);
                            using (var observable = new ManualResetEvent(false))
                            {
                                DownloadStringCompletedEventHandler action = (sender, e) =>
                                {
                                    html = e.Result;
                                    observable.Set();
                                };
                                web.DownloadStringCompleted += action;
                                web.DownloadStringAsync(new Uri(url));
                                observable.WaitOne();
                                token.ThrowIfCancellationRequested();
                                web.DownloadStringCompleted -= action;
                            }

                            // HTML要素に追加してXHTMLなHTML文書に
                            var head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd\">\r\n<html><body>\r\n";
                            var tail = "</body></html>";
                            html     = head + html + tail;

                            // XHTML文書としてパース
                            var doc         = new XmlDocument();
                            doc.XmlResolver = xpr;
                            doc.LoadXml(html);
                            XmlNamespaceManager nm = new XmlNamespaceManager(doc.NameTable);
                            nm.AddNamespace("p", doc.DocumentElement.NamespaceURI);

                            // XPathを使って名前とコメントを抽出
                            foreach (XmlNode div in doc.SelectNodes("/p:html/p:body/p:div", nm))
                            {
                                String name    = "";
                                String comment = "";
                                var nodes      = div.SelectNodes("p:div/text()", nm);
                                if (nodes != null)
                                {
                                    name = nameRegex.Replace(nodes[0].InnerText, "$1");
                                }
                                nodes = div.SelectNodes("p:div/p:a/p:span", nm);
                                if (nodes != null && nodes.Count > 0)
                                {
                                    name = nodes[0].InnerText;
                                }
                                nodes   = div.SelectNodes("p:div/p:span", nm);
                                comment = nodes[1].InnerText;
                                Console.WriteLine("{0}: {1}", name, comment);
                                ++count;
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        Console.WriteLine("//// 停止要求を受け停止");
                    }
                }
            }, token);

            // 上記をタスクとして実行しておき、Enterキーで中止指示
            Console.ReadLine();
            cancelSource.Cancel();

            // 終了を待つ
            job.Wait();
        }
Пример #2
0
        static void Main(string[] args)
        {
            var cancelSource = new CancellationTokenSource();
            CancellationToken token = cancelSource.Token;

            Task job = Task.Factory.StartNew(() =>
            {
                using (var web = new WebClient() { Encoding = Encoding.UTF8 })
                {
                    token.Register(() => {
                        web.CancelAsync();
                    });
                    int count = 0;
                    var html = web.DownloadString("http://livetube.cc/ユーザー/タイトル");

                    // ストリームのURLを取得
                    Match m = new Regex("var comment_entry_id = \"([^\"]*)\";").Match(html);
                    var stream_id = "";
                    if (m.Success && (m.Groups.Count > 1))
                    {
                        stream_id = m.Groups[1].Value;
                    }

                    // HTMLのパースにXMLパーサーを使う
                    // XMLの文字実体参照は5つしかないのでXHTMLとしてパースする
                    // ただしW3Cにアクセスしにいくと迷惑なのでDTDをここからダウンロードして保存しておく
                    // www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd
                    FileInfo dtdFile = new FileInfo("xhtml11-flat.dtd");
                    Uri dtdPublicUri = new Uri("http://www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd");
                    var xpr = new DummyXmlResolver();
                    using (FileStream fs = dtdFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        xpr.Add(dtdPublicUri, fs);
                    }

                    var nameRegex = new Regex("^\\s*\\d+\\s:\\s*(.*)\\s$");
                    try
                    {
                        while (true)
                        {
                            // 必要なコメントをダウンロードする(中身はHTML要素)
                            var url = String.Format("http://livetube.cc/stream/{0}.comments.{1}", stream_id, count);
                            using (var observable = new ManualResetEvent(false))
                            {
                                DownloadStringCompletedEventHandler action = (sender, e) =>
                                {
                                    html = e.Result;
                                    observable.Set();
                                };
                                web.DownloadStringCompleted += action;
                                web.DownloadStringAsync(new Uri(url));
                                observable.WaitOne();
                                token.ThrowIfCancellationRequested();
                                web.DownloadStringCompleted -= action;
                            }

                            // HTML要素に追加してXHTMLなHTML文書に
                            var head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11-flat.dtd\">\r\n<html><body>\r\n";
                            var tail = "</body></html>";
                            html = head + html + tail;

                            // XHTML文書としてパース
                            var doc = new XmlDocument();
                            doc.XmlResolver = xpr;
                            doc.LoadXml(html);
                            XmlNamespaceManager nm = new XmlNamespaceManager(doc.NameTable);
                            nm.AddNamespace("p", doc.DocumentElement.NamespaceURI);

                            // XPathを使って名前とコメントを抽出
                            foreach (XmlNode div in doc.SelectNodes("/p:html/p:body/p:div", nm))
                            {
                                String name = "";
                                String comment = "";
                                var nodes = div.SelectNodes("p:div/text()", nm);
                                if (nodes != null)
                                {
                                    name = nameRegex.Replace(nodes[0].InnerText, "$1");
                                }
                                nodes = div.SelectNodes("p:div/p:a/p:span", nm);
                                if (nodes != null && nodes.Count > 0)
                                {
                                    name = nodes[0].InnerText;
                                }
                                nodes = div.SelectNodes("p:div/p:span", nm);
                                comment = nodes[1].InnerText;
                                Console.WriteLine("{0}: {1}", name, comment);
                                ++count;
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        Console.WriteLine("//// 停止要求を受け停止");
                    }
                }
            }, token);

            // 上記をタスクとして実行しておき、Enterキーで中止指示
            Console.ReadLine();
            cancelSource.Cancel();

            // 終了を待つ
            job.Wait();
        }