現在では、多くの大規模なサイトでは、爬虫類での要求の同じIP番号と周波数を制限抗IP制限ポリシーを取るために、または強制着陸検証の数に達した後に同じIPを要求します。私たちはこの制限を克服するために、プロキシIPを使用する必要があります。この時点で、我々は有刺鉄線西ハイ匿名プロキシIPプロセスを経てクロールCipian DotnetSpiderフレームワークを紹介します。
DotnetSpiderフレームワークの紹介
DotnetSpiderは、.NETコア爬虫類である各クローラ部分のためのパッケージは比較的成熟している、実質的に箱から出してオープンソース開発プロジェクト、GitHubのダウンロード:
https://github.com/dotnetcore/DotnetSpider
基本的な操作のいくつかの例をダウンロード、次DotnetSpider.Sample、CnblogsSpiderの例で見てみましょうでサンプルソリューションを使用する方法を知っています。
CnblogsSpider次のように、爬虫類のいくつかの初期設定を行うために呼び出さ実行初期化()メソッド:
protected override async Task Initialize()
{
NewGuidId();
Depth = 3;
AddDataFlow(new ListNewsParser()).AddDataFlow(new ConsoleStorage());
await AddRequests("https://news.cnblogs.com/n/page/1/");
}
最も重要なの一つは、3つの部分、ListNewsParser、ConsoleStorageと最終AddRequestsで構成されています。ListNewsParserたちはクロールとどのように結果を返すようにしたいWebクローラーのパースを定義する方法である、ConsoleStorageは、私たちのクロールの結果、あなたがターゲットURLをクロール爬虫類を指定されているAddRequests保存爬虫類を定義する方法です。下には、我々はListNewsParserとConsoleStorageコードを見て。
class ListNewsParser : DataParser
{
public ListNewsParser()
{
Required = DataParserHelper.CheckIfRequiredByRegex("news\\.cnblogs\\.com/n/page");
// 如果你还想翻页则可以去掉注释
//FollowRequestQuerier =
// BuildFollowRequestQuerier(DataParserHelper.QueryFollowRequestsByXPath(".//div[@class='pager']"));
}
protected override Task<DataFlowResult> Parse(DataFlowContext context)
{
var news = context.Selectable.XPath(".//div[@class='news_block']").Nodes();
foreach (var item in news)
{
var title = item.Select(Selectors.XPath(".//h2[@class='news_entry']"))
.GetValue(ValueOption.InnerText);
var url = item.Select(Selectors.XPath(".//h2[@class='news_entry']/a/@href")).GetValue();
var summary = item.Select(Selectors.XPath(".//div[@class='entry_summary']"))
.GetValue(ValueOption.InnerText);
var views = item.Select(Selectors.XPath(".//span[@class='view']")).GetValue(ValueOption.InnerText)
.Replace(" 人浏览", "");
var request = CreateFromRequest(context.Response.Request, url);
request.AddProperty("title", title);
request.AddProperty("summary", summary);
request.AddProperty("views", views);
context.AddExtraRequests(request);
}
return Task.FromResult(DataFlowResult.Success);
}
}
キーは()、最終的に辞書タイトル、概要、ビューに解析でXPathによるランディングページの情報を取得するために、解析()にあります。我々は、書き込み爬虫類にしたい場合は、あなたがしたいと私たちが望む結果にパッケージ化情報を取得することにより)、その後DataParserクラスから継承し、メソッド解析で解析し、(実装することのXpathを新しいクラスを作成したり、他の方法ですることができます。
/// <summary>
/// 控制台打印解析结果(所有解析结果)
/// </summary>
public class ConsoleStorage : StorageBase
{
/// <summary>
/// 根据配置返回存储器
/// </summary>
/// <param name="options">配置</param>
/// <returns></returns>
public static ConsoleStorage CreateFromOptions(SpiderOptions options)
{
return new ConsoleStorage();
}
protected override Task<DataFlowResult> Store(DataFlowContext context)
{
var items = context.GetData();
Console.WriteLine(JsonConvert.SerializeObject(items));
return Task.FromResult(DataFlowResult.Success);
}
}
ConsoleStorageたちはDataParserで取得した出力データを保存する方法を定義することで、キーストアにある()、私たちは、コンソールでのJSON文字列出力にシリアライズされたオブジェクトの結果があることがわかります。現在DotnetSpiderは、そのようなコンソール出力として、のようにMySQLの/のSQLServerに保存し、保存出力JSONファイルをいくつかの一般的なストレージ・クラスをカプセル化した、プログラムDotnetSpiderを見るためにデータフロー・ストレージフォルダを解くことができます。同様に、我々は()、継承StorageBaseクラスと実装Storeへの唯一の必要性を自分のストレージをカスタマイズすることができ、メソッドファイルには、データベースまたはキャッシュ定義はに保存されます。
西とげプロキシIPは、ウェブ解析をクロール
西刺しネット代理店の公式アドレスhttps://www.xicidaili.com/nn/
てみましょうのは、我々が取得したいF12プロキシIPとポートでの要素の位置を参照してください
ページングされているページを、訪問したページの数は、評価のURLアクセスの背面にありますページ数を指定しました。我々は唯一のテーブルを登ると、データを取る必要があるので、テーブルのページID =「ip_list」内のすべてのデータは、その各行から取得することができます。以下はDataParserクラスを書き始めます。
class MyParser : DataParser<IPDataEntry>
{
protected override Task<DataFlowResult> Parse(DataFlowContext context)
{
var typeName = typeof(IPDataEntry).FullName;
//首先取得table元素
var table = context.Selectable.Select(Selectors.XPath(".//table[@id='ip_list']")).GetValue();
//取得table行数
var rowcount = System.Text.RegularExpressions.Regex.Matches(table, @"</tr>").Count;
//遍历table每一行,取得其中的ip和port
for (int i = 2; i <= rowcount; i++)
{
//IP和端口分别在第二列和第三列
var IP = context.Selectable.Select(Selectors.XPath($".//table[@id='ip_list']//tr[{i}]/td[2]/text()")).GetValue();
var PORT = context.Selectable.Select(Selectors.XPath($".//table[@id='ip_list']//tr[{i}]/td[3]/text()")).GetValue();
ProxyDataItem proxy = new ProxyDataItem()
{
IpAddress = IP,
Port = PORT
};
//验证抓取到的ip和端口是否可用,可用则加入到结果中
if (ValidateHelper.ValidateProxy(proxy))
{
context.AddData(typeName + (i - 1),
new IPDataEntry
{
IP = IP,
PORT = PORT
});
//Console.WriteLine($"{IP}:{PORT}");
}
}
return Task.FromResult(DataFlowResult.Success);
}
}
IPエージェントIPポートとクロール、利用可能なチャネルの上記の表の我々のMyParserクラスでは単に検証結果に保存されているIPDataEntryで利用可能なIPの建物になります。今、我々はキャッシュし、少ない使用するための永続ストレージ、そこのRedisキャッシュ、Redisのをしないので、しばしば失敗し、プロキシIP不安定性の存在に起因し、その結果を保持するためのストレージクラスを記述する必要があり、私が見ることができるクリアブログの記事C#Redisの利用やヘルプクラス
ここでは、RedisStorageカテゴリであります:
public class RedisStorage : StorageBase
{
/// <summary>
/// 根据配置返回存储器
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public static RedisStorage CreateFromOptions(SpiderOptions options)
{
return new RedisStorage();
}
protected override Task<DataFlowResult> Store(DataFlowContext context)
{
RedisHelper redisHelper = new RedisHelper("localhost");
var items = context.GetData();
var list = new List<IPDataEntry>();
foreach (var item in items)
{
list.Add(item.Value as IPDataEntry);
}
//先将缓存中的旧数据情掉
redisHelper.delKey("IPDATA");
//将新抓取的数据存入缓存
redisHelper.addList<IPDataEntry>("IPDATA",list);
return Task.FromResult(DataFlowResult.Success);
}
}
最後に、我々はProgram.csのDotnetSpider.Sampleソリューションとランで書いたIPDataSpiderを呼び出します。ここでは、爬虫類を見て、プロキシIPをキャッシュする書き込みを使い果たし
、これらはすべてのコンテンツBenpianは、コードの必要性があるが、ダウンロードに行くことができます