关于gecco爬虫框架
如果对gecco还没有了解可以参看一下gecco的github首页。gecco爬虫十分的简单易用。之前有一篇文章《教您使用java爬虫gecco抓取JD商品信息》,使用的是传统的注解方式,建议看这篇文章前先了解之前的文章。这里介绍一下DynamicGecco方式,比之前更简单,抓取全部京东商品只要3个类就能搞定了。
什么是DynamicGecco
DynamicGecco的目的是在不定义SpiderBean的情况下实现爬取规则的运行时配置。其实现原理是采用字节码编程,动态生成SpiderBean,而且通过自定义的GeccoClassLoader实现了抓取规则的热部署。通常我们可以利用DynamicGecco实现下面这些特性:
- 已经定义了ORM(如:hiberante)的bean,将注解动态的加载到ORM的bean中,可以很方便的将页面格式化后入库
- 很多类似的网站的抓取,SpiderBean都一样,只是提取元素的cssPath不一样,为了不构建很多重复的SpiderBean,可以考虑动态生成SpiderBean
- 通过配置的方式抓取页面,通过后台管理系统、配置文件等配置抓取规则,动态的将配置规则转换成SpiderBean
- 利用动态SpiderBean可以构建可视化爬虫,利用可视化工具构建抓取规则,将规则动态转换为SpiderBean
规则定义
爬虫的抓取规则,如matchUrl、csspath、ajax等不需要再使用注解方式注入SpiderBean中,利用DynamicGecco直接定义。下面是抓取全部JD商品的规则定义:
public static void main(String[] args) {
//对应原来的Category和HrefBean类
Class<?> category = DynamicGecco.html()
.stringField("parentName").csspath("dt a").text().build()
.listField("categorys",
DynamicGecco.html()
.stringField("url").csspath("a").href().build()
.stringField("title").csspath("a").text().build()
.register()).csspath("dd a").build()
.register();
//对应原来的AllSort类
DynamicGecco.html()
.gecco("http://www.jd.com/allSort.aspx", "consolePipeline", "allSortJsonPipeline")
.requestField("request").request().build()
.listField("mobile", category)
.csspath(".category-items > div:nth-child(1) > div:nth-child(2) > div.mc > div.items > dl").build()
.register();
//对应ProductBrief类
Class<?> productBrief = DynamicGecco.html()
.stringField("code").csspath(".j-sku-item").attr("data-sku").build()
.stringField("title").csspath(".p-name> a > em").text().build()
.stringField("preview").csspath(".p-img > a > img").image("", "data-lazy-img", "src").build()
.stringField("detailUrl").csspath(".p-name > a").href(true).build()
.register();
//对应ProductList类
DynamicGecco.html()
.gecco("http://list.jd.com/list.html?cat={cat}&delivery={delivery}&page={page}&JL={JL}&go=0", "consolePipeline", "productListJsonPipeline")
.requestField("request").request().build()
.intField("currPage").csspath("#J_topPage > span > b").text().build()
.intField("totalPage").csspath("#J_topPage > span > i").text().build()
.listField("details", productBrief).csspath("#plist .gl-item").build()
.register();
//对应ProductDetail类
DynamicGecco.html()
.gecco("http://item.jd.com/{code}.html", "consolePipeline")
.stringField("code").requestParameter().build()
.stringField("title").csspath("#name > h1").text().build()
.stringField("detail").csspath("#product-detail-2").build()
.stringField("image").csspath("#spec-n1 img").image("d:/gecco/jd/img").build()
.field("price", FieldType.type(JDPrice.class)).ajax("http://p.3.cn/prices/get?type=1&pdtk=&pdbp=0&skuid=J_{code}").build()
.field("jdAd", FieldType.type(JDad.class)).ajax("http://cd.jd.com/promotion/v2?skuId={code}&area=1_2805_2855_0&cat=737%2C794%2C798").build()
.register();
HttpGetRequest start = new HttpGetRequest("http://www.jd.com/allSort.aspx");
start.setCharset("GBK");
GeccoEngine.create()
.classpath("com.geccocrawler.gecco.demo.jd")
.start(start)
.interval(2000)
.run();
}
规则定义后,启动GeccoEngine即可,和之前没有两样,可以看出来,之前的例子定义了7个Bean,但是这里只需要一个类就都搞定了。
语法讲解
- html():定义一个html页面爬虫,对应原来HtmlBean接口。对已经存在的类可以指定参数html(className),如果不定义系统会自动生成类名。
- json():定义一个json数据的爬虫,对应原来JsonBean接口。对已经存在的类可以指定参数json(className),如果不定义系统会自动生成类名。
- gecco(matchUrl, pipelines...):定义url匹配模式和pipeline处理器。对应原来@Gecco注解
- existField(fileName):定义一个存在的属性,用来承载抽取出来的内容,如果属性不存在,不会创建新的属性
- stringField(fileName):定义一个属性,用来承载抽取出来的内容,如果属性已经存在则复用,如果不存在会生成一个新的属性。目前支持的原始类型属性包括:intField, floatField, longField, doubleField,shortField
- requestField(fileName):对应HttpRequest类型的属性
- listField(fileName,memberClass):对应一个list类型属性,memberClass表示List里元素的数据类型
- field(fileName,memberClass):定义memberClass类型的属性,这是一个比较灵活的定义属性的方式,可以任意指定属性类型
- csspath(csspath):jsoup的抽取元素规则,对应原来@HtmlField注解
- text():对应原来@Text注解
- href():对应原来@Href注解
- image():对应原来@Image注解
- attr():对应原来@Attr注解
- ajax():对应原来@Ajax注解
- jsonpath():对应原来@JSONPath注解
- build():构建属性抽取规则
- loadClass():构建整个Bean,使用GeccoClassLoader加载进JVM
- register():完成loadClass()并且注册到GeccoEngine(GeccoEngine必须后启动才有效)
JsonPipeline
Pipeline的写法也和之前有所区别,由于是运行时生成的Bean,不能像以前那样直接使用定义的Bean,Gecco会将所有Bean都转换为JSONObject,通过json操作来获取抓取来的信息。下面是DynamicJD定义的两个Pipeline:
类别处理Pipeline,对应原来的AllSortPipeline
@PipelineName("allSortJsonPipeline")
public class AllSortJsonPipeline extends JsonPipeline {
public static List<HttpRequest> sortRequests = new ArrayList<HttpRequest>();
@Override
public void process(JSONObject allSort) {
HttpRequest currRequest = HttpGetRequest.fromJson(allSort.getJSONObject("request"));
JSONArray categorys = allSort.getJSONArray("mobile");
process(currRequest, categorys);
}
private void process(HttpRequest currRequest, JSONArray categorys) {
if(categorys == null) {
return;
}
for(int i = 0; i < categorys.size(); i++) {
JSONObject category = categorys.getJSONObject(i);
JSONArray hrefs = category.getJSONArray("categorys");
for(int j = 0; j < hrefs.size(); j++) {
String url = hrefs.getJSONObject(j).getString("url")+"&delivery=1&page=1&JL=4_10_0&go=0";
SchedulerContext.into(currRequest.subRequest(url));
}
}
}
}
产品列表处理Pipeline,对应原来的ProductListPipeline
@PipelineName("productListPipeline")
public class ProductListPipeline implements Pipeline<ProductList> {
@Override
public void process(ProductList productList) {
HttpRequest currRequest = productList.getRequest();
//下一页继续抓取
int currPage = productList.getCurrPage();
int nextPage = currPage + 1;
int totalPage = productList.getTotalPage();
if(nextPage <= totalPage) {
String nextUrl = "";
String currUrl = currRequest.getUrl();
if(currUrl.indexOf("page=") != -1) {
nextUrl = StringUtils.replaceOnce(currUrl, "page=" + currPage, "page=" + nextPage);
} else {
nextUrl = currUrl + "&" + "page=" + nextPage;
}
SchedulerContext.into(currRequest.subRequest(nextUrl));
}
}
}
以上三个类就完成了JD全部商品的抓取,是不是足够简单了。那注解方式还有必要用吗?当然还是有必要的,你会发现,DynamicGecco虽然足够简单,但是他的可理解性、可读性还是没有注解方式好,对于Gecco框架的新手我还是建议先从注解方式开始。
动态增加修改规则
DynamicGecco通过自定义的GeccoClassLoader实现了规则的热部署,这个是个很有用的功能,你可以想象,假如你有一个管理后台,通过配置就能实现爬虫规则的定义,写爬虫不需要再开发程序,直接配置一下就可以了,如果管理系统做的足够强大,你甚至可以做成可视化的方式,csspath都不需要自己写了。这里还是以最简单的MyGithub为例讲解动态增加修改规则。
启动爬虫引擎
动态增加修改规则,意味着你可以在没有规则的情况下先启动爬虫引擎。规则可以在你定义好后再加入爬虫引擎。
//初始化爬虫引擎,此时由于没有初始请求,爬虫引擎会阻塞初始队列,直到获取到初始请求
GeccoEngine ge = GeccoEngine.create("com.geccocrawler.gecco.demo.dynamic")
.interval(5000)
.loop(true)
.engineStart();
定义爬取规则
爬虫规则的定义和之前讲的基本一致,唯一不同的是register()改成loadClass()。loadClass()用于先启动爬虫引擎后定义规则的场景
//定义爬取规则
Class<?> rule1 = DynamicGecco
.html()
.gecco("https://github.com/xtuhcy/gecco", "consolePipeline")
.stringField("title").csspath(".repository-meta-content").text(false).build()
.intField("star").csspath(".pagehead-actions li:nth-child(2) .social-count").text(false).build()
.intField("fork").csspath(".pagehead-actions li:nth-child(3) .social-count").text().build()
.loadClass();
注册新的规则
犹豫规则定好后并没有注册,通过下面的方法注册规则:
//注册规则
ge.register(rule1);
初始请求
加入初始请求队列后,爬虫就开始工作了
//加入初始请求,爬虫引擎开始工作
ge.getScheduler().into(new HttpGetRequest("https://github.com/xtuhcy/gecco"));
更新规则
如果这时我们希望更新一下抓取规则,比如不想抓star了,我们可以这样更新:
try {
//开始更新规则
ge.beginUpdateRule();
//修改规则
Class<?> newRule = DynamicGecco
.html(rule1.getName())
.gecco("https://github.com/xtuhcy/gecco", "consolePipeline")
.intField("fork").csspath(".pagehead-actions li:nth-child(3) .social-count").text().build()
.removeField("star")
.loadClass();
//注册新规则
ge.register(newRule);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
//规则更新完毕
ge.endUpdateRule();
}
下线已有规则
已经定义好的规则,我们可以将其下线,方法如下:
try {
//开始更新规则
ge.beginUpdateRule();
//下线之前的规则
ge.unregister(rule);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
//规则更新完毕
ge.endUpdateRule();
}
到此,爬虫规则的增加/修改/删除都已经实现。可以愉快的配置爬虫规则了!
完整的的Demo代码可以参考github上的源代码,位于com.geccocrawler.gecco.demo.dynamic包下。
相关推荐
此项目是一个简单的淘宝数据抓取工具,使用的是struts框架开发的。当你在首页输入一个商品的时候,就可以得到此商品在淘宝的查询结果,包括商品名,价格,以及销量。
主要介绍了PHP实现采集抓取淘宝网单个商品信息,本文是一种实现思路,使用file_get_contents函数实现,并给出了采集正则,需要的朋友可以参考下
使用python抓取上交所上市公司信息和下载深交所上市公司信息,然后保存到mysql中,并可以从mysql导出到excel。
抓取商品工具能抓取各网店平台的商品数据,商品详细的描述,商品图片,一次性抓取到自己的店铺,省时省力!数据包处理,可以将淘宝的数据包转换为拍拍的数据包,也可以将拍拍的数据包转换为淘宝的数据包!
根据商品id指定需要抓取的商品范围,抓取指定商品详情页价格、库存、运费信息,存入数据库作数据分析和参考 使用步骤: 1.搭建python环境,配置好环境变量 2.配置数据库环境,根据本地数据库连接修改alibaba.py中的...
本程序编写了一个从网页中抓取信息(如最新的头条新闻,新闻的来源,标题,内容等)的类,而且本程序文件夹中含有word文件,文件将介绍如何使用这个类来抓取网页中需要的信息。文件将以抓取博客园首页的博客标题和...
用scrapy框架写的京东爬虫,可以抓取京东商品信息和评论,努力学习的路上
抓取商品软件_甩手工具箱全能抓取神器、完整高效。不管是标题、主题、描述、销售属性及属性图统统都能完整的复制下来。可以保证所抓取的商品和之前的商品是一模一样,商品属性和销售属性99%相同。
淘宝天猫商品数据抓取,代码和exe都在里面
可以通过本实例学习selenium框架,文件中记录了selenium的一些常用操作,通过selenium可以模拟浏览器的操作从网页文件中获取想要的信息。
抓取G529数据中...完成! 抓取G1204数据中...完成! 抓取G279数据中...完成! 抓取G276数据中...完成! 抓取G1022数据中...完成! 抓取G280数据中...完成! 抓取G1206数据中...完成! 抓取G1224数据中...完成! 抓取G818数据...
申明:本脚本没有涉及JD账号登录,没有抓取任何JD敏感信息,仅在手动执行一次脚本时会读取JD公开商品页面的商品名称和价格,如有任何敏感侵权问题,请联系我删除。 申明:本脚本没有涉及JD账号登录,没有抓取任何JD...
使用正则表达式和requests,抓取猫眼 TOP100 的电影信息
自己写的一个京东商品数据抓取的东西,不够完善,但还可以用。现在只支持京东,后期可以加入淘宝、天猫、易迅等电商
下面小编就为大家分享一篇使用selenium抓取淘宝的商品信息实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
自己写的京东商城商品数据信息抓取程序。输入查询条件,系统自动查询匹配的商品信息并提取商品的部分关键信息展示,可以导出excel。
网页爬虫工具能够抓取网页信息的软件网页爬虫工具[PClawer] V1.1 绿色版 PClawer 是一款定制功能较强的网页抓取工具,需要用到正则表达式,适合高级用户使用
Python网络爬虫教程 使用python抓取及分析互联网数据 共13页.pptx
东东tools,JD CK抓取提交工具,支持JDX