[开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [三] 配置式爬虫
[DotnetSpider 系列目录]
上一篇介绍的基本的使用方式,自由度很高,但是编写的代码相对就多了。而我所在的行业其实大部分都是定题爬虫, 只需要采集指定的页面并结构化数据。为了提高开发效率, 我实现了利用实体配置的方式来实现爬虫
创建 Console 项目
利用NUGET添加包
DotnetSpider2.Extension
定义配置式数据对象
- 数据对象必须继承 SpiderEntity
- EntityTableAttribute中可以定义数据名称、表名及表名后缀、索引、主键或者需要更新的字段
- EntitySelector 定义从页面数据中抽取数据对象的规则
- TargetUrlsSelector定义符合规则(正则)的目标链接, 用于加入到队列中
定义一个原始的数据对象类
public class Product : SpiderEntity
{
}
使用Chrome打开京东商品页 http://list.jd.com/list.html?cat=9987,653,655&page=2&JL=6_0_0&ms=5#J_main
- 使用快捷键F12打开开发者工具
- 选中一个商品,并观察Html结构

可以看到每个商品都在class为gl-i-wrap j-sku-item的DIV下面,因此添加EntitySelector到数据对象Product的类名上面。( XPath的写法不是唯一的,不熟悉的可以去W3CSCHOLL学习一下, 框架也支持使用Css甚至正则来选择出正确的Html片段)。
[EntitySelector(Expression = "//li[@class='gl-item']/div[contains(@class,'j-sku-item')]")]
public class Product : SpiderEntity
{
}
添加数据库及索引信息
[EntityTable("test", "sku", EntityTable.Monday, Indexs = new[] { "Category" }, Uniques = new[] { "Category,Sku", "Sku" })]
[EntitySelector(Expression = "//li[@class='gl-item']/div[contains(@class,'j-sku-item')]")]
public class Product : SpiderEntity
{
}假设你需要采集SKU信息,观察HTML结构,计算出相对的XPath, 为什么是相对XPath?因为EntitySelector已经把HTML截成片段了,内部的Html元素查询都是相对于EntitySelector查询出来的元素。最后再加上数据库中列的信息
[EntityTable("test", "sku", EntityTable.Monday, Indexs = new[] { "Category" }, Uniques = new[] { "Category,Sku", "Sku" })]
[EntitySelector(Expression = "//li[@class='gl-item']/div[contains(@class,'j-sku-item')]")]
public class Product : SpiderEntity
{
[PropertyDefine(Expression = "./@data-sku")]
public string Sku { get; set; }
}爬虫内部,链接是通过Request对象来存储信息的,构造Request对象时可以添加额外的属性值,这时候允许数据对象从Request的额外属性值中查询数据
[EntityTable("test", "sku", EntityTable.Monday, Indexs = new[] { "Category" }, Uniques = new[] { "Category,Sku", "Sku" })]
[EntitySelector(Expression = "//li[@class='gl-item']/div[contains(@class,'j-sku-item')]")]
public class Product : SpiderEntity
{
[PropertyDefine(Expression = "./@data-sku")]
public string Sku { get; set; } [PropertyDefine(Expression = "name", Type = SelectorType.Enviroment)]
public string Category { get; set; }
}
配置爬虫(继承EntitySpider)
public class JdSkuSampleSpider : EntitySpider
{
public JdSkuSampleSpider() : base("JdSkuSample", new Site
{
//HttpProxyPool = new HttpProxyPool(new KuaidailiProxySupplier("快代理API"))
})
{
} protected override void MyInit(params string[] arguments)
{
Identity = Identity ?? "JD SKU SAMPLE"; ThreadNum = ;
// dowload html by http client
Downloader = new HttpClientDownloader(); // storage data to mysql, default is mysql entity pipeline, so you can comment this line. Don't miss sslmode.
AddPipeline(new MySqlEntityPipeline("Database='mysql';Data Source=localhost;User ID=root;Password=;Port=3306;SslMode=None;"));
AddStartUrl("http://list.jd.com/list.html?cat=9987,653,655&page=2&JL=6_0_0&ms=5#J_main", new Dictionary<string, object> { { "name", "手机" }, { "cat3", "" } });
AddEntityType<Product>();
}
}
其中AddStartUrl第二个参数Dictionary<string, object>就是用于Enviroment查询的数据
TargetUrlsSelector,可以配置数据链接的合法性验证,以及目标URL的获取。如下表示目标URL的获取区域是由XPATH选择,并且要符合正则表达式 &page=[0-9]+&
[EntityTable("test", "jd_sku", EntityTable.Monday, Indexs = new[] { "Category" }, Uniques = new[] { "Category,Sku", "Sku" })]
[EntitySelector(Expression = "//li[@class='gl-item']/div[contains(@class,'j-sku-item')]")]
[TargetUrlsSelector(XPaths = new[] { "//span[@class=\"p-num\"]" }, Patterns = new[] { @"&page=[0-9]+&" })]
public class Product : SpiderEntity
{
[PropertyDefine(Expression = "./@data-sku")]
public string Sku { get; set; } [PropertyDefine(Expression = "name", Type = SelectorType.Enviroment)]
public string Category { get; set; }
}

添加一个MySql的数据管道,只需要配置好连接字符串即可
context.AddPipeline(new MySqlEntityPipeline("Database='test';Data Source=localhost;User ID=root;Password=1qazZAQ!;Port=3306"));
完整代码
public class JdSkuSampleSpider : EntitySpider
{
public JdSkuSampleSpider() : base("JdSkuSample", new Site
{
//HttpProxyPool = new HttpProxyPool(new KuaidailiProxySupplier("快代理API"))
})
{
} protected override void MyInit(params string[] arguments)
{
Identity = Identity ?? "JD SKU SAMPLE"; ThreadNum = ;
// dowload html by http client
Downloader = new HttpClientDownloader(); // storage data to mysql, default is mysql entity pipeline, so you can comment this line. Don't miss sslmode.
AddPipeline(new MySqlEntityPipeline("Database='mysql';Data Source=localhost;User ID=root;Password=;Port=3306;SslMode=None;"));
AddStartUrl("http://list.jd.com/list.html?cat=9987,653,655&page=2&JL=6_0_0&ms=5#J_main", new Dictionary<string, object> { { "name", "手机" }, { "cat3", "" } });
AddEntityType<Product>();
}
} [EntityTable("test", "jd_sku", EntityTable.Monday, Indexs = new[] { "Category" }, Uniques = new[] { "Category,Sku", "Sku" })]
[EntitySelector(Expression = "//li[@class='gl-item']/div[contains(@class,'j-sku-item')]")]
[TargetUrlsSelector(XPaths = new[] { "//span[@class=\"p-num\"]" }, Patterns = new[] { @"&page=[0-9]+&" })]
public class Product : SpiderEntity
{
[PropertyDefine(Expression = "./@data-sku", Length = )]
public string Sku { get; set; } [PropertyDefine(Expression = "name", Type = SelectorType.Enviroment, Length = )]
public string Category { get; set; } [PropertyDefine(Expression = "cat3", Type = SelectorType.Enviroment)]
public int CategoryId { get; set; } [PropertyDefine(Expression = "./div[1]/a/@href")]
public string Url { get; set; } [PropertyDefine(Expression = "./div[5]/strong/a")]
public long CommentsCount { get; set; } [PropertyDefine(Expression = ".//div[@class='p-shop']/@data-shop_name", Length = )]
public string ShopName { get; set; } [PropertyDefine(Expression = ".//div[@class='p-name']/a/em", Length = )]
public string Name { get; set; } [PropertyDefine(Expression = "./@venderid", Length = )]
public string VenderId { get; set; } [PropertyDefine(Expression = "./@jdzy_shop_id", Length = )]
public string JdzyShopId { get; set; } [PropertyDefine(Expression = "Monday", Type = SelectorType.Enviroment)]
public DateTime RunId { get; set; }
}
运行爬虫
public class Program
{
public static void Main(string[] args)
{
JdSkuSampleSpider spider = new JdSkuSampleSpider();
spider.Run();
}
}


不到57行代码完成一个爬虫,是不是异常的简单?
代码地址
https://github.com/zlzforever/DotnetSpider 望各位大佬加星 
参与开发或有疑问
博文写得比较早, 框架修改有时会来不及更新博文中的代码, 请查看DotnetSpider.Sample项目中的样例爬虫
QQ群: 477731655
[开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [三] 配置式爬虫的更多相关文章
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [三] 配置式爬虫
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 上一篇介绍的基本的使用方式,自由度很高,但是编写的代码相对 ...
- [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师的要求,大多是招JA ...
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 为什么要造轮子 同学们可以去各大招聘网站查看一下爬虫工程师 ...
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [五] 如何做全站采集?
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 如何做全站采集? 很多同学加群都在问, 如何使用Dotne ...
- [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [二] 基本使用
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 使用环境 Visual Studio 2015 or later .NET 4 ...
- [开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [四] JSON数据解析
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 场景模拟 假设由于漏存JD SKU对应的店铺信息.这时我们需要重新完全采集所有 ...
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [四] JSON数据解析
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 场景模拟 接上一篇, JD SKU对应的店铺信息是异步加载 ...
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] [二] 基本使用
[DotnetSpider 系列目录] 一.初衷与架构设计 二.基本使用 三.配置式爬虫 四.JSON数据解析与配置系统 五.如何做全站采集 使用环境 Visual Studio 2017 .NET ...
- 爬虫框架: DotnetSpider
[开源 .NET 跨平台 数据采集 爬虫框架: DotnetSpider] [一] 初衷与架构设计 一 ,为什么要造轮子 有兴趣的同学可以去各大招聘网站看一下爬虫工程师的要求,大多是JAVA,PYTH ...
随机推荐
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- [ZigBee] 4、ZigBee基础实验——中断
前言 上一篇介绍了CC2530的IO的基础知识,并用LED的控制来展示如何配置并控制GPIO的输出,用KEY状态的读取实验来展示如何读取GPIO的状态.从上一节的KEY状态读取的代码看出是采用轮训方式 ...
- Gradle与Gatling脚本集成
Gatling作为次时代的性能测试工具,由于其API简洁明了.性能出众,越来越受欢迎.但是运行Gatling脚本却有诸多不便,其提供的默认方式不是很方便.考虑到Gatling脚本本质上是Scala类, ...
- Git bash 配置ssh key
问题描述 昨天为了配置Qt create中的Git,把我一直在使用的Github删除了,今本以为,这样git的一些配置还在,可是,今天上传一些提交的时候,提示我,git没有密钥.梳理一下,这个简单的配 ...
- Permission is only granted to system apps
原文地址http://jingyan.baidu.com/article/9113f81b2e7a8c2b3314c711.html
- linux命令 - ln - 创建和删除软、硬链接
linux命令 - ln - 创建和删除软.硬链接 在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号.文件属性保存在索引结点里,在访问文件 ...
- dic+css页面布局分享
HTML部分代码<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...
- c#将list集合转换为datatable的简单办法
public static class ExtensionMethods { /// <summary> /// 将List转换成DataTabl ...
- Command /usr/bin/codesign failed with exit code 1
刚刚碰到相同的问题,自己解决了,很简单,profile冲突,(自己遇到的现象是之前的profile关联的certificate过期,然后重新生成 了certificate和更新了profile.但是是 ...
- 移动web开发之视口viewport
× 目录 [1]布局视口 [2]视觉视口 [3]理想视口[4]meta标签[5]总结 前面的话 在CSS标准文档中,视口viewport被称为初始包含块.这个初始包含块是所有CSS百分比宽度推算的根源 ...