ウェブサイトからの情報取得

2019年6月19日

LINQを使ったパターン(HTMLデータの改行単位でチェック)

行をまたいで情報が書かれていると逃す可能性はあります

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;

namespace WebScraping
{
    class Program
    {
        static void Main()
        {
            // 調べたいURL
            var sourceURL = @"https://www.xxx.xxx.xxx/";

            // 含まれているパターン(この例では[img src="http] が含まれている行を取得)
            var containsPattern = @"img src=""http";

            // 抜き出す箇所 (frontPattern + 抜き出したいデータ + endPattern)
            // この例では、img src="{抜き出し}" のイメージ
            // @"img src="""; は、"img src=\"";と同じこと。 \"で "を表しています
            var frontPattern = @"img src=""";
            // @""""; は、"\"";と同じこと。
            var endPattern = @"""";

            // 抜き出した結果の取得メソッド 
            // 戻り値(URLのHTMLコード, 抜き出した結果)
            // C#7から使えるタプルを採用 複数の戻り値(URLのHTMLコード, 抜き出した結果)
            (string sourceData, List<string> selectedData) = GetExtractedDataFromUrl(sourceURL,
                                                                containsPattern,
                                                                frontPattern,
                                                                endPattern);

            // 結果の表示
            Console.WriteLine(sourceData);
            selectedData.ForEach(Console.WriteLine);
        }

        /// <summary>
        /// URLからデータの抽出
        /// </summary>
        /// <returns>URLのHTMLテキストファイル、抽出したデータ</returns>
        /// <param name="url">抽出したいURL</param>
        /// <param name="selLine">含まれている文字列(行の取得)</param>
        /// <param name="frontPat">抽出する条件(抜き出す文字列の直前のパターン</param>
        /// <param name="endPat">抽出する条件(抜き出す文字列の直後のパターン</param>
        private static (string dataList, List<string> selectedData) GetExtractedDataFromUrl(string url,
                                                                                           string selLine,
                                                                                           string frontPat,
                                                                                           string endPat)
        {
            // HTML取得ファイルの取得変数
            var dataList = "";

            // ウェブクライアントクラスを使って、URLのデータを取得、dataListに代入
            using (var wc = new WebClient())
            {
                dataList = wc.DownloadString(url);
            }

            // 改行コード毎にListに代入
            var listSourceHTML = dataList.Split("\n").ToList();

            // データの抽出のためのマッチパターン(正規表現)
            // (ExtractedData: 翻訳 抽出したデータ 個人で考えたグループ名)
            var anchor = $"({frontPat})(?<ExtractedData>.*?)([{endPat}])";

            // 戻り値は2つ。HTML文字列と条件にマッチしたデータ
            return (dataList, listSourceHTML
                            // マッチするデータがある行のみ抽出
                            .Where(x => Regex.IsMatch(x, selLine)).ToList()
                            // .ValueでMatchクラスのデータ部分のみ取得できる。オプションで、大文字小文字の違いを無視。
                            .Select(x => Regex.Match(x, anchor, RegexOptions.IgnoreCase).Groups["ExtractedData"].Value)
                            // リストに変換
                            .ToList());
        }
    }
}

取得したHTMLデータで一括抽出するパターン

改行コードを無視するため、行をまたいだ情報でも抽出できます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;

namespace WebScraping
{
    class Program
    {
        static void Main()
        {
            // 調べたいURL
            var sourceURL = @"https://www.xxx.xxx/";
            // var sourceURL = @"https://www.ac-illust.com/main/detail.php?id=1233910&word=ハロウィンアイコン一覧%28アイソメ%29";

            // 抜き出す箇所 frontPattern + 抜き出したいデータ + endPattern
            // 次の設定は、img src="{抜き出し}" のイメージ
            // @"img src="""; は、"img src=\"";と同じこと。 \"で "を表しています
            var frontPattern = @"img src=""";
            // @""""; は、"\"";と同じこと。
            var endPattern = @"""";

            // 抜き出した結果の取得メソッド 
            // C#7から使えるタプルを採用 複数の戻り値(URLのHTMLコード, 抜き出した結果)
            (string sourceData, List<string> selectedData) = GetExtractedDataFromUrl(sourceURL,
                                                                                     frontPattern,
                                                                                     endPattern);

            // 抜き出したデータの中でも、共通で含まれているパターンだけ取得(img src="http が含まれている行を取得)
            var containsPattern = @"http";

            // 必要な情報だけ選択(今回は、httpが含まれているデータのみ使います)
            var containData = selectedData.Where(x => x.Contains(containsPattern)).ToList();

            // 結果の表示
            Console.WriteLine(sourceData);
            containData.ForEach(Console.WriteLine);
        }

        /// <summary>
        /// URLからデータの抽出
        /// </summary>
        /// <returns>URLのHTMLテキストファイル、抽出したデータ</returns>
        /// <param name="url">抽出したいURL</param>
        /// <param name="frontPat">抽出する条件(抜き出す文字列の直前のパターン</param>
        /// <param name="endPat">抽出する条件(抜き出す文字列の直後のパターン</param>
        private static (string dataList, List<string> extractedData) GetExtractedDataFromUrl(string url,
                                                                                               string frontPat,
                                                                                               string endPat)
        {
            // HTML取得ファイルの取得変数
            var dataList = "";

            // ウェブクライアントクラスを使って、URLのデータを取得、dataListに代入
            using (var wc = new WebClient())
            {
                dataList = wc.DownloadString(url);
            }

            // データの抽出のためのマッチパターン(正規表現)
            // (ExtractedData: 翻訳 抽出したデータ 個人で考えたグループ名)
            var anchor = $"({frontPat})(?<ExtractedData>.*?)([{endPat}])";

            // 正規表現でマッチする条件のオプションセット
            var options =
                        // 大文字小文字の違いを無視
                        RegexOptions.IgnoreCase |
                        // 単一行モード(改行を含む文字列でも、それを改行とみなさず他の文字と同等に処理)
                        RegexOptions.Singleline;

            // 抽出したデータをセットする変数(List)
            var extractedData = new List<string>();

            // 正規表現でマッチしたデータのみ抽出
            foreach (Match match in Regex.Matches(dataList, anchor, options))
            {
                // マッチしたデータのみ抽出データにAddする。
                // .ValueでMatchクラスのデータ部分のみ取得できる
                extractedData.Add(match.Groups["ExtractedData"].Value);
            }

            // 戻り値は2つ。HTML文字列と条件にマッチしたデータ
            return (dataList, extractedData);
        }
    }
}

複数の値を返すメソッドとその使用例

C#,正規表現

Posted by hidepon