こんにちは、ひつじ先輩です。
C#で正規表現を使い、文字列から任意のパターンを抽出します。
とくに、スクレイピングをやりたい人には役立つはずです。
- サイトのソースコードを取得
- 文字列から欲しい部分を抽出
がスクレイピングの流れ。
この記事では、2の部分について書きます。
C#で正規表現のコード

static List<string> extractProxy(string source)
{
//抽出結果をいれるためのリスト
List<string> proxies = new List<string>();
//抽出したい文字列を正規表現で書く
Regex r = new Regex(@"class=""."">(\d.*?)</a></li>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
//正規表現と入力を比較。一致した文字列をリストに入れる。
MatchCollection mc = r.Matches(source);
//正規表現のための特殊なリスト型から普通の文字列リストへコピー
foreach (Match m in mc) proxies.Add(m.Groups[1].Value);
return proxies;
}
- 文字列が入力される
- 正規表現でマッチした部分を抽出
- 当てはまる文字列をリストで返す
をやっています。
具体的には、プロキシのリストをふくむHTMLソース(string source)からプロキシリストを抽出してます。
HTMLをよく見る
正規表現で欲しい部分だけ抽出するため、まずパターンを見つけます。
取ってきたソースを見たとき、
<a title=”AF” onMouseOver=”s(‘DE’,’mx1.flintvpscoin.com’)” onMouseOut=”d()” class=”A”>51.68.92.17:8080</a></li>
<a title=”AF” onMouseOver=”s(‘AF’,’mail2.aitek.ru’)” onMouseOut=”d()” class=”B”>210.61.46.165:3128</a></li>
<a title=”AF” onMouseOver=”s(‘RU’,’ip-fmtc-jkt.polaris.net.id’)” onMouseOut=”d()” class=”A”>212.243.175.126:80</a></li>
といった表現が連続していたとします。
HTMLソースのこの部分で、サイト上にプロキシのリストを表示させています。
「class=”A”>」と「</a></li>」のあいだの太字が、プロキシです。
正規表現で抽出
プロキシがどこに書いてあるか分かったら、今度はそれを抽出します。
コードでは、
Regex r = new Regex(@”class=””.””>(\d.*?)</a></li>“, RegexOptions.IgnoreCase | RegexOptions.Singleline);
で、入力された文字列のどこを抽出するか決めています。
“class=””.””>(\d.*?)</a></li>“
が正規表現です。
HTMLを見た結果、
「class=”A”>」もしくは「class=”B”>」
と
「</a></li>」
のあいだにプロキシがあると分かっています。
正規表現の
“class=””.””>(\d.*?)</a></li>“
は、それとマッチするようになっています。
以下、部分ごとに説明します。
class=””.””>
「class=”A”>」のような文字列とマッチする部分を探します。
「.」はなんでも、1文字という意味。
Aのところは、何か1文字入っていればマッチします。
(\d.*?)
括弧の中の正規表現にマッチした部分を、実際に抽出(切り出し)しています。
括弧内の「\d.*?」は、何か数字から始まる文字列。
という意味。
- 「\d」は半角数字
- 「.」は任意の一文字
- 「*?」は直前文字の0回以上の繰り返し
「51.68.92.17:8080」のような、プロキシそのものが一致。
抽出されます。
</a></li>
この部分は固定された表現。
一致する部分を探しており、ここまでを1セットとしています。
これが検出されるとまた次の、「class=”A”>」のような文字列を探します。
正規表現部分の意味
まとめると、
“class=””.””>(\d.*?)</a></li>“
の意味は、
「class=”A”>」や「class=”B”>」と「</a></li>」の間の、数字から始まる文字列を抽出。
です。
プロキシリストを抽出

正規表現で、プロキシリストを抽出するコード。
「抽出する」部分以外も含めた全体は、このようになります。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net; //追加してください。
using System.IO; //追加してください。
using System.Text.RegularExpressions; //追加してください。(正規表現を利用するため)
namespace getProxy
{
class Program
{
static void Main(string[] args)
{
string proxySite = "http://www.cybersyndrome.net/pla5.html"; //プロキシリストのあるサイトURL
string source = ""; //プロキシリストをふくむウェブソースを入れるハコ
if (getSource(proxySite, ref source)) //サイトソースをダウンロードする
{
//ダウンロード成功したときの処理
Console.WriteLine("ソースのダウンロードに成功しました...URL:" + proxySite);
//ダウンロードしたソースを(念のため)記録しておく
StreamWriter st = new StreamWriter("source.txt", false); //ソースを書き込むファイルを開く
st.Write(source); //ダウンロードしたソースを書き込む
st.Close(); //ファイルを閉じる
//ソースからプロキシを取り出す
List<string> proxies = extractProxy(source);
//プロキシをファイルに書き込む
StreamWriter st2 = new StreamWriter("proxies.txt", false); //プロキシを書き込むファイルを開く
foreach (string proxy in proxies)
{
st2.Write(proxy + "\n"); //プロキシを書き込む
}
st2.Close(); //ファイルを閉じる
Console.ReadKey(); //キー入力待ち
}
else
{
//ダウンロード失敗したときの処理
Console.WriteLine("ダウンロードに失敗しました。");
Console.ReadKey(); //キー入力待ち
}
}
static List<string> extractProxy(string source)
{
//プロキシをいれるためのリスト
List<string> proxies = new List<string>();
//取り出したい文字列を正規表現で書く
Regex r = new Regex(@"class=""."">(\d.*?)</a></li>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
//書いた正規表現とソースを比較。一致した文字列をリストに入れる。
MatchCollection mc = r.Matches(source);
//正規表現のための特殊なリスト型から普通の文字列リストへコピー
foreach (Match m in mc) proxies.Add(m.Groups[1].Value);
return proxies;
}
static bool getSource(string url, ref string source)
{
HttpWebRequest webreq = (HttpWebRequest)
WebRequest.Create(url);
try
{
//ウェブサイトの内容をダウンロード
HttpWebResponse webres = (HttpWebResponse)webreq.GetResponse();
Stream st = webres.GetResponseStream();
//ウェブサイトの内容をハコにいれる
StreamReader sr = new StreamReader(st);
source = sr.ReadToEnd();
st.Close();
sr.Close();
}
catch (WebException e)
{
Console.WriteLine(e.Message); //ダウンロードに失敗した場合、理由を表示
Console.WriteLine("getSourceで例外が発生しました。\n" + url);
return false;
}
return true;
}
}
}
- getSourceメソッドでHTMLをダウンロード
- extractProxyメソッドでプロキシを抽出
しています。
正規表現を使うため、
using System.Text.RegularExpressions;
は、コードの最初に必ず必要です。



コメント