AngleSharpで画像スクレイピング

まずは,この辺を一読します.

HttpClientをusingで囲わないでください - Qiita

【C#】AngleSharpの使い方メモ - Qiita

AngleSharpでスクレイピングする - Qiita

C#でモダンにスクレイピングするならAngleSharp - Qiita

背景

 ある方のブログをよく見ているのですが,印刷した際に画像が小さく,ちょっと見にくくなってます・・・.
 そこで,HTMLを解析して,画像だけ頂いちゃおうっていうのが今回の狙いです.

開発環境

 Windows7(サポート切れごめんなさい)
 VisualStudio2019 16.5.4
 .net Framework 4.7.2

まずはNuGet

 まずはNuGetでAngleSharpを落としてきます.
f:id:iinebot:20200602085154p:plain

さっそくコード!

 んで,書いていきますが,HttpClientをusingで囲わないでください - Qiitaのとおり,メンバーにHttpClientを宣言します.
 批判しているわけではないですが,他のQiita記事はusingしてます.
 実は,ある方のブログ専用で作ってる関係で,記事ごとのタイトルと記事ごとのURLが取得済みなので,その前提で話が進みます・・・.

メンバー
        static WebProxy proxy = new WebProxy(@"proxyserver.co.jp:portNO"); //必要であれば
        static HttpClientHandler handler = new HttpClientHandler()
        {
            Proxy = proxy,
        };
        // HttpClient is intended to be instantiated once per application, rather than per-use. See Remarks.
        static readonly HttpClient client = new HttpClient(handler);
        public Form1()
        {
            InitializeComponent();
        }
スクレイピング
        private async System.Threading.Tasks.Task scrapper(string urlstring, string folder)
        {
            var doc = default(IHtmlDocument);

            using (var stream = await client.GetStreamAsync(new Uri(urlstring)))
            {
                HtmlParser parser = new HtmlParser(); //htmlパーサーにぶっこむ
                doc = await parser.ParseDocumentAsync(stream);
            }

            var imgTag = doc.QuerySelectorAll("img");// HTMLからimgタグの値を取得する
            foreach (IHtmlImageElement n in imgTag)
            {
                string uri = n.Source;
                string[] parser = { "?" };
                if ((uri.Contains("png") || uri.Contains("jpg")) && uri.Contains("落としたいブログのユーザ名"))
                {
                    Debug.WriteLine(uri.Split(parser, StringSplitOptions.RemoveEmptyEntries)[0]);
                    FileDownload(uri.Split(parser, StringSplitOptions.RemoveEmptyEntries)[0], folder);
                }
            }
        }
ファイルダウンロード部
        private void FileDownload(string url, string folder)
        {
            try
            {
                string path = System.IO.Directory.GetCurrentDirectory() + "\\" + folder;
                if (!Directory.Exists(path))
                {
                    System.IO.DirectoryInfo di = System.IO.Directory.CreateDirectory(path);
                }
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                req.UserAgent = "Chromeなどのブラウザのユーザエージェント";
                req.Proxy = proxy;
                string[] sep = { "/" };
                string[] fileName = url.Split(sep, StringSplitOptions.RemoveEmptyEntries);
                WebResponse res = req.GetResponse();
                using (Stream st = res.GetResponseStream())
                {
                    using (FileStream fs = new FileStream(path +"\\" + fileName.Last(), FileMode.Create))
                    {
                        st.CopyTo(fs); //ストリームのコピー(.NET Framework 4以降)
                    }
                }
            }
            catch (WebException exc)
            {

            }
        }
ボタンクリック部
        private async void button1_ClickAsync(object sender, EventArgs e)
        {
            //TextBoxに入力するフォーマットは URL,フォルダ名 です.
            StringReader rs = new System.IO.StringReader(textBox1.Text);//StringReaderにテキストボックスをぶっこむ
                        
            while (rs.Peek() > -1)//1行ずつ読み込んで
            {
                string[] sep = { "," };
                string[] paths = rs.ReadLine().ToString().Split(sep, StringSplitOptions.RemoveEmptyEntries);//カンマで分ける
                await scrapper(paths[0],paths[1]);
            }
            Debug.WriteLine("END");
        }

実行結果

こんな感じで,実行ファイルと同じフォルダに格納できました!
f:id:iinebot:20200602101436p:plain