webMagic爬取Ajax中post请求详解
由于项目需求,需要在某电商网站上爬取一些商品数据,由于初次接触webMagic所以难免碰到了一些坑,在这里与大家分享一下。
1.对于静态html的数据爬取,我就不做详细介绍,因为获取不到真正有用的数据。
2.目前前端页面大多是js和Ajax渲染,增加了爬取难度,最开始参考别人的post带参请求并没有出现想要的数据,具体的核心代码(无效实例)如下:
@Override
public void process(Page page) {
Request request = new Request("http://www.szzfcg.cn/newmall/newGoodDisplay.do");
request.setMethod(HttpConstant.Method.POST);
List<NameValuePair> nvs = new ArrayList<NameValuePair>();
nvs.add(new BasicNameValuePair("method","listRefresh"));
nvs.add(new BasicNameValuePair("makeSupplyId","17873"));
nvs.add(new BasicNameValuePair("sqlOrderBy","synth ASC"));
NameValuePair[] values = nvs.toArray(new NameValuePair[] {});
Map<String, Object> params = new HashMap<String, Object>();
params.put("NameValuePair",values);
request.setExtras(params);
page.addTargetRequest(request);
page.putField("价格", page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_price z']").toString());
}
如果以此种方法去模拟发送post请求,会不停去发送请求,并且得不到自己想要的数据,对此我用postman测试发送相同的带参数的post请求发现请求成功,如下图:
很明显已经查出了数据,后来经过分析和测试,本人发现了一个非常有意思的方法,postman查询地址如下
是通过参数的拼接去发送请求,不是get请求,对于post显示参数请求可以参考post提交详解该博主的文章,我不做过多阐述。
回到正题,直接上正确代码
public static void main(String[] args) {
System.out.println("开始爬取内容");
for (int i = 1; i <= 133; i++) {
Request request = new Request("http://www.szzfcg.cn/newmall/newGoodDisplay.do?method=listRefresh&makeSupplyId=9651&sqlOrderBy=num_sales DESC&page="+i+"");
request.setMethod(HttpConstant.Method.POST);
Spider.create(new ShoppingTest()).addRequest(request).thread(5).run();
}
直接将需要的参数拼接到请求地址上发送请求,这主要是爬取多个列表页面的数据,所以做了一个循环请求,然后根据相应的webmagic表达式获取相应的数据,代码如下:
List<String> priceList = new ArrayList();
List<String> sellList = new ArrayList();
List<String> nameList = new ArrayList();
priceList = page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_price z']/text()").all();
sellList = page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_xl z']/b/text()").all();
nameList = page.getHtml().xpath("//div[@class='goodlist_tit']/a/text()").all();
完整的实例代码
package us.codecraft.webmagic.processor.example;
import us.codecraft.webmagic.MybatisManager.TopDataManager;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.domain.Goods;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.utils.HttpConstant;
import java.util.*;
public class ShoppingTest implements PageProcessor {
private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000);
@Override
public void process(Page page) {
List<String> priceList = new ArrayList();
List<String> sellList = new ArrayList();
List<String> nameList = new ArrayList();
priceList = page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_price z']/text()").all();
sellList = page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_xl z']/b/text()").all();
nameList = page.getHtml().xpath("//div[@class='goodlist_tit']/a/text()").all();
for (int i = 0; i < 20; i++) {
Goods goods = new Goods();
goods.setPrice(priceList.get(i).substring(1));
goods.setNum(sellList.get(i));
goods.setName(nameList.get(i));
String price = goods.getPrice();
String num = goods.getNum();
Double i1 = Double.parseDouble(price) * Double.parseDouble(num);
goods.setTotal(i1);
System.out.println(goods.toString());
//数据存入数据库
TopDataManager.createTopData(goods);
}
priceList.clear();
sellList.clear();
/* page.putField("价格", page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_price z']").toString());
page.putField("销量", page.getHtml().xpath("//div[@class='goodlist_item']//span[@class='goodlist_xl z']/b/text()"));
page.putField("text", page.getHtml().xpath("//div[@class='header wp']/a//span[@class='z']/text()").toString());*/
}
@Override
public Site getSite() {
return site;
}
public static void main(String[] args) {
System.out.println("开始爬去内容路径");
//初始化数据库连接
TopDataManager.initialConnection();
for (int i = 1; i <= 133; i++) {
Request request = new Request("http://www.szzfcg.cn/newmall/newGoodDisplay.do?method=listRefresh&makeSupplyId=9651&sqlOrderBy=num_sales DESC&page="+i+"");
request.setMethod(HttpConstant.Method.POST);
Spider.create(new ShoppingTest()).addRequest(request).thread(5).run();
}
/* //直接在路径后添加请求参数
Request request = new Request("http://www.szzfcg.cn/newmall/newGoodDisplay.do?method=listRefresh&makeSupplyId=17873&page=3&sqlOrderBy=num_sales DESC");
request.setMethod(HttpConstant.Method.POST);*/
}
}
爬取结果如下:
总结:
这是我研究几天的成果,可能比较简单,但是真的简单有效,与别的博主可能方法不太一样,希望能帮助大家。
第一次写博客可能比较糟糕,望大家谅解,以后会慢慢改善,求各位大佬指教。