##詳情頁抓取 商品的基本信息抓取完成後,就要針對每一個商品的詳情頁進行抓取,能夠看到詳情頁的地址格式通常以下: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提問,固然也能夠在博客中留言。