`
xtuhcy
  • 浏览: 142284 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

教您使用DynamicGecco抓取JD全部商品信息

阅读更多

关于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包下。

0
1
分享到:
评论

相关推荐

    亚马逊爬虫抓取商品信息并数据分析.zip

    亚马逊爬虫抓取商品信息并数据分析.zip亚马逊爬虫抓取商品信息并数据分析.zip亚马逊爬虫抓取商品信息并数据分析.zip亚马逊爬虫抓取商品信息并数据分析.zip亚马逊爬虫抓取商品信息并数据分析.zip亚马逊爬虫抓取商品...

    JD-python爬取京东商品信息_爬取商品信息_京东_

    本教程将聚焦于使用Python语言来爬取京东平台的商品信息,包括商品详情页、商品名称、价格、评价人数以及商家信息。 首先,我们需要了解Python中的几个关键库,如requests和BeautifulSoup,它们是进行网页抓取的...

    抓取淘宝商品的价格,物品名,销量等信息

    标题中的“抓取淘宝商品的价格,物品名,销量等信息”指的是通过网络爬虫技术从淘宝网站上获取商品的相关数据,这些数据主要包括商品的名称、价格和销售量。这是一个非常实用的技术,尤其对于数据分析、市场研究或者...

    python抓取淘宝天猫网页商品详情Demo

    5. **异步抓取与Scrapy框架**:对于大量商品详情的抓取,可以考虑使用Scrapy框架,它支持异步请求,能更高效地处理批量爬取任务。Scrapy包含了中间件、爬虫、调度器等组件,能更好地管理爬取过程。 6. **注意法律...

    python爬虫1688一件代发电商工具(二)-抓取商品详情页价格库存运费信息(selenium)

    根据商品id指定需要抓取的商品范围,抓取指定商品详情页价格、库存、运费信息,存入数据库作数据分析和参考 使用步骤: 1.搭建python环境,配置好环境变量 2.配置数据库环境,根据本地数据库连接修改alibaba.py中的...

    京东,淘宝,苏宁,亚马逊爬虫抓取商品信息并分析数据.zip

    标题中的“京东,淘宝,苏宁,亚马逊爬虫抓取商品信息并分析数据”指的是使用网络爬虫技术从这四个知名电商平台(京东、淘宝、苏宁、亚马逊)获取商品的相关信息,并进行数据分析的过程。这个过程通常涉及以下几个...

    京东爬虫,可抓取京东商品信息和评论

    2. `items.py`:定义要抓取的数据结构,如商品信息(名称、价格、评价等)和评论内容。 3. `settings.py`:配置文件,设置爬虫的行为,如下载延迟、中间件、数据去重策略等。 4. `pipelines.py`:定义数据处理流程,...

    tp5 利用QueryList + PhantomJS实现抓取淘宝京东天猫商品数据

    在IT行业中,网络爬虫是一项重要的技术,用于自动化地从互联网上抓取大量信息。本教程将探讨如何利用ThinkPHP5(简称tp5)框架,结合QueryList库和PhantomJS浏览器内核来抓取淘宝、京东、天猫等电商平台上商品的数据...

    Python-淘宝天猫商品数据抓取代码和exe都在里面

    这个资源主要涵盖了使用Python进行网络爬虫技术,特别是针对淘宝和天猫平台的商品数据抓取。Python作为一种强大的编程语言,因其简洁明了的语法和丰富的库支持,常被用于Web爬虫开发。在描述中提到的"exe"文件可能是...

    使用requests框架爬取jd商品信息

    ### 使用requests框架爬取JD商品信息 #### 一、引言 随着互联网技术的发展,网络爬虫成为了一种重要的数据获取手段。对于Python初学者来说,掌握基础的爬虫技术不仅可以帮助他们更好地理解网络数据的结构,还能为...

    京东商品数据抓取

    本项目是关于“京东商品数据抓取”的实现,虽然目前仅支持京东平台,但具备扩展到其他电商平台如淘宝、天猫、易迅等的潜力。下面将详细讲解这个项目的相关知识点。 1. **网络爬虫技术**:数据抓取的基础是网络爬虫...

    淘宝商品抓取工具 - 通过页面抓取淘宝网的商品

    淘宝商品抓取工具是一款专为数据分析师、电商从业者或研究人员设计的应用程序,它允许用户从淘宝网的商品搜索页面中高效地获取大量商品信息。这款工具的主要功能是通过自动化的方式抓取网页上的商品数据,以便进行...

    python抓取淘宝天猫网页商品详情Demo.zip

    本项目"python抓取淘宝天猫网页商品详情Demo.zip"是一个利用Python进行网络数据抓取的示例,主要涉及到以下几个核心知识点: 1. **网络请求库**:在Python中,我们通常使用如`requests`库来发送HTTP请求,获取网页...

    抓取商品,抓取宝贝工具,数据包处理

    抓取商品工具能抓取各网店平台的商品数据,商品详细的描述,商品图片,一次性抓取到自己的店铺,省时省力!数据包处理,可以将淘宝的数据包转换为拍拍的数据包,也可以将拍拍的数据包转换为淘宝的数据包!

    京东商品数据信息抓取(32位Windows可用)

    本项目“京东商品数据信息抓取(32位Windows可用)”正是这样一个工具,旨在帮助用户自动化地获取京东商城的商品信息,提取关键数据,并将其整理成易于分析的Excel格式。 首先,我们要理解什么是数据抓取。数据抓取...

    网页抓取教程.zip

    网页抓取,也被称为网络爬虫或数据抓取,是一种自动化技术,用于从互联网上收集大量信息。在Java EE和Android开发中,网页抓取是一个重要技能,可以帮助开发者获取网站上的结构化数据,如新闻、产品信息、评论等,...

    网页Html抓取爬虫测试工具

    这款工具是用C#编程语言编写的,旨在简化和优化网页信息提取的过程,帮助开发者高效地进行网页数据挖掘工作。 在网页抓取过程中,HTML抓取是最基础的步骤。HTML(HyperText Markup Language)是构成网页的主要标记...

    Winform抓取赶集网车票转让信息

    《使用Winform抓取赶集网车票转让信息的实现详解》 在信息化时代,数据的获取和处理已经成为日常工作中不可或缺的一部分。本文将详细介绍如何利用Winform和C#技术,结合正则表达式,实现一个自动抓取赶集网车票转让...

    scrapy框架实现JD指定类目宝贝信息抓取(可供参考学习)

    在"JD指定类目宝贝信息抓取"这个项目中,我们将探讨如何利用Scrapy来抓取京东平台上的特定商品信息。首先,我们需要安装Scrapy框架,这可以通过在命令行输入`pip install scrapy`来完成。 一、Scrapy项目创建与结构...

    抓取速卖通商品信息完整源码

    本篇文章将详细讲解如何利用编程技术实现抓取速卖通商品信息的完整源码,帮助你掌握这一实用技能。 首先,我们需要了解速卖通的商品页面结构。速卖通是阿里巴巴集团旗下的全球B2C电商平台,其商品页面包含大量丰富...

Global site tag (gtag.js) - Google Analytics