教您使用java爬蟲gecco抓取JD所有商品信息(三)

##詳情頁抓取 商品的基本信息抓取完成後,就要針對每一個商品的詳情頁進行抓取,能夠看到詳情頁的地址格式通常以下:http://item.jd.com/1861098.html。咱們創建商品詳情頁的Bean:javascript

@Gecco(matchUrl="http://item.jd.com/{code}.html", pipelines="consolePipeline")
public class ProductDetail implements HtmlBean {

	private static final long serialVersionUID = -377053120283382723L;

	/**
	 * 商品代碼
	 */
	@RequestParameter
	private String code;
	
	/**
	 * 標題
	 */
	@Text
	@HtmlField(cssPath="#name > h1")
	private String title;
	
	/**
	 * ajax獲取商品價格
	 */
	@Ajax(url="http://p.3.cn/prices/get?skuIds=J_[code]")
	private JDPrice price;

	/**
	 * 商品的推廣語
	 */
	@Ajax(url="http://cd.jd.com/promotion/v2?skuId={code}&area=1_2805_2855_0&cat=737%2C794%2C798")
	private JDad jdAd;
	
	/*
	 * 商品規格參數
	 */
	@HtmlField(cssPath="#product-detail-2")
	private String detail;
	
	public JDPrice getPrice() {
		return price;
	}

	public void setPrice(JDPrice price) {
		this.price = price;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public JDad getJdAd() {
		return jdAd;
	}

	public void setJdAd(JDad jdAd) {
		this.jdAd = jdAd;
	}

	public String getDetail() {
		return detail;
	}

	public void setDetail(String detail) {
		this.detail = detail;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}
}

@RequestParameter能夠獲取@Gecco裏定義的url變量{code}。css

@Ajax是頁面中的ajax請求,JD的商品價格和推廣語都是經過ajax請求異步獲取的,gecco支持異步ajax請求,指定ajax請求的url地址,url中的變量能夠經過兩種方式指定。html

一種是花括號{},能夠獲取request的參數相似@RequestParameter,例子中獲取推廣語的{code}是matchUrl="http://item.jd.com/{code}.html"中的code;java

一種是中括號[],能夠獲取bean中的任意屬性。例子中獲取價格的[code]是變量private String code;。git

##json數據的元素抽取 商品的價格是經過ajax獲取的,ajax通常返回的都是json格式的數據,這裏須要將json格式的數據抽取出來。咱們先定義價格的Bean:github

public class JDPrice implements JsonBean {

	private static final long serialVersionUID = -5696033709028657709L;

	@JSONPath("$.id[0]")
	private String code;
	
	@JSONPath("$.p[0]")
	private float price;
	
	@JSONPath("$.m[0]")
	private float srcPrice;

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}

	public float getSrcPrice() {
		return srcPrice;
	}

	public void setSrcPrice(float srcPrice) {
		this.srcPrice = srcPrice;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

}

咱們獲取的商品價格信息的json數據格式爲:[{"id":"J_1861098","p":"6488.00","m":"7488.00"}]。能夠看到是一個數組,由於這個接口其實能夠批量獲取商品的價格。json數據的數據抽取使用@JSONPath註解,語法是使用的fastjson的JSONPath語法。ajax

JDad的抓取相似,下面是Bean的代碼:redis

public class JDad implements JsonBean {

	private static final long serialVersionUID = 2250225801616402995L;

	@JSONPath("$.ads[0].ad")
	private String ad;

	@JSONPath("$.ads")
	private List<JSONObject> ads;
	
	public String getAd() {
		return ad;
	}

	public void setAd(String ad) {
		this.ad = ad;
	}
	
	public List<JSONObject> getAds() {
		return ads;
	}

	public void setAds(List<JSONObject> ads) {
		this.ads = ads;
	}

}

##學會分析ajax請求 目前爬蟲抓取頁面內容針對ajax請求有兩種主流方式:chrome

  • 一種是模擬瀏覽器將頁面徹底繪製出來,好比能夠利用htmlunit。這種方式存在一個問題就是效率低,由於頁面中的全部ajax都會被請求,並且須要解析全部的js代碼。gecco能夠經過自定義downloader來實現這種方式
  • 還一種就是須要哪些ajax就執行哪些,這就要開發人員分析網頁中的ajax請求,得到請求的地址,好比抓取JD的商品價格的地址@Ajax(url="http://p.3.cn/prices/mgets?skuIds=J_[code]")。並且這個地址以後可能會變。

這兩種方式都有各自的優缺點,gecco經過擴展都支持,本人仍是更傾向於使用第二種方式。json

下面說說怎麼分析頁面中的ajax請求,仍是要利用chrome的開發者模式,network選項能夠看到頁面中的全部請求:

輸入圖片說明 能夠看到請求的地址是:http://p.3.cn/prices/get?type=1&area=1_2805_2855&pdtk=&pduid=836516317&pdpin=&pdbp=0&skuid=J_1861098&callback=cnp。咱們去掉其餘參數只留下商品的代碼,發現同樣能夠訪問,http://p.3.cn/prices/get? skuid=J_1861098就是咱們要請求的地址。

##gecco的其餘一些有用的特性

  • gecco支持頁面中的定義的全局javascript變量的提取,如頁面中定義的var變量。
  • gecco支持分佈式抓取,經過redis管理startRequest實現分佈式抓取。

##源碼 所有源代碼能夠在gecco的github上下載,代碼位於src/test/java/com/geccocrawler/gecco/demo/jd包下。若是使用過程當中發現任何bug歡迎Pull request,或者經過Issue提問,固然也能夠在博客中留言。

相關文章
相關標籤/搜索