2021SC@SDUSC
接上篇
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抓取完成后一般需要进行持久化,也就是将商品的基本信息入库,入库的方式有很多种,gecco支持整合spring,可以利用spring进行pipeline的开发。本篇是进行了控制台输出。ProductList的业务处理还有一个很重要的任务,就是对分页的处理,列表页通常都有很多页,如果需要全部抓取,我们需要将下一页的链接入抓取队列。
@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参数达到分页抓取的目的。至此,所有的商品的列表信息都已经可以正常抓取了。