##抓取商品列表信息 AllSortPipeline已经将须要进一步抓取的商品列表信息的连接提取出来了,能够看到连接的格式是:http://list.jd.com/list.html?cat=9987,653,659&delivery=1&JL=4_10_0&go=0。所以咱们创建商品列表的Bean——ProductList,代码以下:css
@Gecco(matchUrl="http://list.jd.com/list.html?cat={cat}&delivery={delivery}&page={page}&JL={JL}&go=0", pipelines={"consolePipeline", "productListPipeline"}) public class ProductList implements HtmlBean { private static final long serialVersionUID = 4369792078959596706L; @Request private HttpRequest request; /** * 抓取列表项的详细内容,包括titile,价格,详情页地址等 */ @HtmlField(cssPath="#plist .gl-item") private List<ProductBrief> details; /** * 得到商品列表的当前页 */ @Text @HtmlField(cssPath="#J_topPage > span > b") private int currPage; /** * 得到商品列表的总页数 */ @Text @HtmlField(cssPath="#J_topPage > span > i") private int totalPage; public List<ProductBrief> getDetails() { return details; } public void setDetails(List<ProductBrief> details) { this.details = details; } public int getCurrPage() { return currPage; } public void setCurrPage(int currPage) { this.currPage = currPage; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; } public HttpRequest getRequest() { return request; } public void setRequest(HttpRequest request) { this.request = request; } }
currPage和totalPage是页面上的分页信息,为以后的分页抓取提供支持。ProductBrief对象是商品的简介,主要包括标题、预览图、详情页地址等。html
public class ProductBrief implements HtmlBean { private static final long serialVersionUID = -377053120283382723L; @Attr("data-sku") @HtmlField(cssPath=".j-sku-item") private String code; @Text @HtmlField(cssPath=".p-name> a > em") private String title; @Image({"data-lazy-img", "src"}) @HtmlField(cssPath=".p-img > a > img") private String preview; @Href(click=true) @HtmlField(cssPath=".p-name > a") private String detailUrl; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPreview() { return preview; } public void setPreview(String preview) { this.preview = preview; } public String getDetailUrl() { return detailUrl; } public void setDetailUrl(String detailUrl) { this.detailUrl = detailUrl; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } }
这里须要说明一下@Href(click=true)的click属性,click属性形象的说明了,这个连接咱们但愿gecco继续点击抓取。对于增长了click=true的连接,gecco会自动加入下载队列中,不须要在手动调用SchedulerContext.into()增长。 ##编写ProductList的业务逻辑 ProductList抓取完成后通常须要进行持久化,也就是将商品的基本信息入库,入库的方式有不少种,这个例子并无介绍,gecco支持整合spring,能够利用spring进行pipeline的开发,你们能够参考gecco-spring这个项目。本例子是进行了控制台输出。ProductList的业务处理还有一个很重要的任务,就是对分页的处理,列表页一般都有不少页,若是须要所有抓取,咱们须要将下一页的连接入抓取队列。git
@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的列表页经过page参数来指定页码,咱们经过替换page参数达到分页抓取的目的。至此,全部的商品的列表信息都已经能够正常抓取了。github