HeyCHのブログ

慢性疲労のへいちゃんです

【C#】5ちゃんねるビューアーを作ろう その1

今回の内容は「5ちゃんねるビューアーを作ろう」シリーズの1つになります。
heych.hatenablog.com

5ちゃんねるのメニュー

メニューは「https://www2.5ch.net/5ch.html」にあります。
5ちゃんねるのメニューは大カテゴリーと小カテゴリーに分かれていて、
小カテゴリーをクリックするとスレッド一覧が表示される感じになっています。
HTMLソースは以下のようになっています。

<br><br><B>地震</B><br>
<a href="//headline.5ch.net/bbynamazu/">地震headline</a><br>
<a href="//egg.5ch.net/namazuplus/">地震速報</a><br>
<a href="//mao.5ch.net/eq/">臨時地震</a><br>
<a href="//himawari.5ch.net/eqplus/">臨時地震+</a><br>
<a href="//rio2016.5ch.net/lifeline/">緊急自然災害</a>
<br><br><B>おすすめ</B><br>
<a href="//krsw.5ch.net/covid19/">COVID-19</a><br>
<a href="//rio2016.5ch.net/lifeline/">緊急自然災害</a>

これを今回はTreeViewで表示しようというわけですから、

  • 大カテゴリーの取得
  • 小カテゴリーの取得+URLの取得および関連付け

を反復的に取得することが必要になると考えられます。

まずはプロジェクトの準備

いつものようにWindowsフォームアプリケーションプロジェクトを作成し、

  1. SplitContainerを配置し、右上の▲から「上下スプリッターの方向」をクリックし、縦型にします。
  2. panel1にもう1つSplitContainerを配置(これは横方向のままでOK)
  3. 上のpanel1にTreeViewを配置し、DockプロパティをFillに設定します。
  4. 上のpanel2にListViewを配置し、DockプロパティをFillに設定します。
  5. 下のpanel2にRichTextBoxを配置し、DockプロパティをFillに、ReadOnlyプロパティをTrueに設定します。

f:id:HeyCH:20200415235130p:plain
できたらForm1をダブルクリックしてForm1_Loadイベントを追加します。

コードの記述

ちょっときたないですが、こんな感じにすればTreeViewに表示できます。
難しい…

        private void Form1_Load(object sender, EventArgs e) {
            string html = "";
            //まずHTMLの取得
            HttpWebRequest req = WebRequest.CreateHttp("https://www2.5ch.net/5ch.html");
            using (var res = req.GetResponse()) {
                using (var r = res.GetResponseStream()) {
                    using (var sr = new StreamReader(r, Encoding.GetEncoding(932))) {
                        html = sr.ReadToEnd();
                    }
                }
            }
            //Treeの作成
            bool stTag = false;
            bool edTag = false;
            bool isAttr = false;
            string currentTag = null;
            string currentAttr = null;
            string tmp = null;
            for (int i = 0; i < html.Length; i++) {
                if (html[i] == '<') {
                    if (html[i + 1] == '/') {
                        if (tmp != null) {
                            if (currentTag == "B") {
                                TreeNode tn = new TreeNode(tmp);
                                treeView1.Nodes.Add(tn);
                            } else if (currentTag == "a" && treeView1.Nodes.Count > 0) {
                                TreeNode tn = new TreeNode(tmp);
                                treeView1.Nodes[treeView1.Nodes.Count - 1].Nodes.Add(tn);
                            }
                        }
                        edTag = true;
                    } else {
                        stTag = true;
                        tmp = null;
                        currentTag = null;
                        currentAttr = null;
                    }
                } else if (html[i] == '>') {
                    if (edTag) currentTag = null;
                    stTag = false;
                    edTag = false;
                    isAttr = false;
                } else if (html[i] == ' ' && stTag) {
                    isAttr = true;
                } else {
                    if (isAttr) currentAttr += html[i];
                    else if (stTag) currentTag += html[i];
                    else if(!edTag &&(currentTag=="B" || currentTag=="a")) {
                        tmp += html[i];
                        if (tmp == "他のサイト") break;
                    }
                }
            }
        }

f:id:HeyCH:20200416234951p:plain