スナックelve 本店

バツイチ40代女の日記です

はてなブログのソースから文字列検索。はてなブックマークから文字列検索。

大嫌いな女が好きな人に絡んでたとするじゃないですか。
「なんで絡んでんの」
って聞いたときに普通に「昔から仲いいよ」とか「友達だよ」と言ってくれればぐぬぬとなっても、納得はするわけです。

「いや、なんかわからんけど絡んできた」

みたいな下らない嘘をつかれるとイラっとしませんか?


そんな枕でなんでこんなタイトルなのか。
好きな人のブログとブクマを検索するために作ったからです(爆)



地雷女の地雷を見せてやんよ!!(たいしたことはない)みんな、自己責任だぜ!!
というわけで環境は
visualstudio.microsoft.com

Visual Studio Community落として.net開発環境いれて、c#のコンソールアプリ作成画面を選択します(早口)

はてなブログ限定。ソースから文字列を検索します。ソースのコメントとかも検索できると思う。

using System;
using System.Net;
using System.Text;
namespace ReadWeb
{
    class Program
    {
        static void Main(string[] args)
        {
            WebClient wc = new WebClient() { Encoding = Encoding.GetEncoding("utf-8") };
            // HTMLソースをダウンロードする
            //そのブログの一番古い記事のURL
            string page = "https://elve.hatenadiary.jp/entry/2018/02/22/231107";
            //検索したい言葉
            string target = "セックス";

            string last_page = "";

            while (page != "")
            {
                if (last_page == page)
                {
                    break;
                }
                string sorce = wc.DownloadString(page);
                wc.Dispose();


                int num = sorce.IndexOf(target) + 1;
                int cnt = 0;
                while (num > 0)
                {
                    cnt++;
                    num = sorce.IndexOf(target, num) + 1;
                }
                // 表示する
                if (cnt > 0)
                {
                    Console.WriteLine("{0}に{1}は{2}回出てきました", page, target, cnt);
                }
                try
                {
                    string nextP = "<span class=\"pager-prev\">";
                    string nextPStart = "<a href=\"";
                    string nextPEnd = "\"";
                    int tmpP = sorce.IndexOf(nextP);
                    int tmpPs = sorce.IndexOf(nextPStart, tmpP + nextP.Length);
                    int tmpPe = sorce.IndexOf(nextPEnd, tmpPs + nextPStart.Length);
                    last_page = page;
                    page = sorce.Substring(tmpPs + nextPStart.Length, tmpPe - tmpPs - nextPStart.Length);

                }
                catch
                {
                    page = "";
                }
            }

        }
    }
}

実行すると
f:id:elve:20200913125417p:plain
こんな感じで検索したい単語がいつの記事に何回出てるかわかります。
出力ファイルにしたほうがいいかもです。

だいぶキモいですね。やめずに行きますよ!!
同じような方法でブクマページも検索してみました。

実際に対象に実行した結果ですw キモイことこの上ないけど気にしたら負けですよ!?
f:id:elve:20200913125955p:plain

ブクマ1ページに20ブクマ入っててそこに何件出てくるかがわかってもあんまり意味ネーナ、と。
中身解析せねば・・・beautifulsoup的なものがほしいぞ・・・

似たようなお悩み
c# - C#プログラマー向けのWebスクレイピング(HTMLAgilityPackまたはPython + beautifulsoup)のためのより良いオプション

HTMLAgilityPackってのを使うといいらしいよ!!
導入はこちらなど参照
www.atmarkit.co.jp

using System;
using System.Net;
using System.Text;
namespace ReadWeb
{
    class Program
    {
        static void Main(string[] args)
        {
            //ブクマページ
            string url = "https://b.hatena.ne.jp/elve/";
            //検索したい文字列
            string target = "男";


            WebClient wc = new WebClient() { Encoding = Encoding.GetEncoding("utf-8") };
            string sorce;
            try 
            { 
                // HTMLソースをダウンロードする
                sorce = wc.DownloadString(url);
                wc.Dispose();
            }
            catch
            {
                Console.WriteLine("url異常?");
                wc.Dispose();
                return;
            }
            //ブクマ数取得
            string cttag = "userprofile-status-count\">";
            int maxBkmS = sorce.IndexOf(cttag) + cttag.Length;
            string toji = "<";
            int maxBkmE = sorce.IndexOf(toji, maxBkmS);
            int maxbm;
            //文字列から数字に変換
            try
            {
                maxbm = Int32.Parse(sorce.Substring(maxBkmS, maxBkmE - maxBkmS).Replace(",", ""));
            }
            catch
            {
                return;
            }
            //ページ数取得
            int last_page = maxbm / 20;
            //端数があったら+1ページ
            if ((maxbm % 20) > 0)
            {
                last_page++;
            }

            for (int i = 1; i <= last_page; i++)
            {
                string page = url + "bookmark?page=" + i.ToString();
                sorce = wc.DownloadString(page);
                wc.Dispose();



                var htmlDoc = new HtmlAgilityPack.HtmlDocument();
                htmlDoc.LoadHtml(sorce);

                var articles
                   = htmlDoc.DocumentNode
                     .SelectNodes(@"//ul[@class=""js-user-bookmark-item-list js-keyboard-controllable-container""]");
                foreach (var article in articles)
                {
                    int displayflg = 0;
                    string[] flg = {"[ ]", "[ ]", "[ ]", "[ ]" };
                    string title = article.SelectSingleNode(@"//h3/a").InnerText;
                    string bkurl1= article.SelectSingleNode(@"//h3/a").GetAttributeValue("href", "");
                    var bkm = article.ParentNode.SelectSingleNode(@"//div [@class=""centerarticle-reaction js-user-bookmark-id-container""]/div[@class=""centerarticle-reaction-comment js-user-bookmark-comment ""]");
                    string bkcmntUrl = bkm.SelectSingleNode(@"//div/span/a").GetAttributeValue("href", "");
                    string bkcmnt = bkm.SelectSingleNode(@"//div/span[@class=""js-comment""]").InnerText;

                    //
                    if (title.IndexOf(target) > 0) { flg[0] = "[*]"; displayflg = 1; }
                    if (bkurl1.IndexOf(target) > 0) { flg[1] = "[*]"; displayflg = 1; }
                    if (bkcmntUrl.IndexOf(target) > 0) { flg[2] = "[*]"; displayflg = 1; }
                    if (bkcmnt.IndexOf(target) > 0) { flg[3] = "[*]"; displayflg = 1; }
                    if (displayflg > 0)
                    {
                        Console.WriteLine("===\n記事タイトル  :{0}{1}", flg[0], title);
                        Console.WriteLine("記事URL    :{0}{1}", flg[1], bkurl1);
                        Console.WriteLine("ブクマURL   :{0}{1}", flg[2], bkcmntUrl);
                        Console.WriteLine("ブクマコメント :{0}{1}\n", flg[3], bkcmnt);

                    }

                }

            }

        }
    }
}

出力こちらもファイルに出したほうがいいかも。
f:id:elve:20200913131409p:plain

こんな感じで検索ワードがある項目に[*]が付きます。あんま意味ないかもw

楽しかった。
もう、関数終了させるのreturnっての忘れるくらいc#触ってなかったけど動くものができてよかったw

参考サイト
配列ってどう書くっけ? から
【C#入門】string(文字列)配列の操作(追加、削除、結合、変換、検索) | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト
割り算のあまりの出し方忘れた。vbaだとmodだけど、Cは%でした。
算術演算子 - C# リファレンス | Microsoft Docs
ベース
ネットワーク上のHTMLファイルの読み込み

html-agility-pack.net