关于webmagic爬取Ajax中post请求详解

时间:2024-03-28 20:24:51

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请求发现请求成功,如下图:
关于webmagic爬取Ajax中post请求详解

很明显已经查出了数据,后来经过分析和测试,本人发现了一个非常有意思的方法,postman查询地址如下
关于webmagic爬取Ajax中post请求详解
是通过参数的拼接去发送请求,不是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);*/


    }
}

爬取结果如下
关于webmagic爬取Ajax中post请求详解

总结
这是我研究几天的成果,可能比较简单,但是真的简单有效,与别的博主可能方法不太一样,希望能帮助大家。
第一次写博客可能比较糟糕,望大家谅解,以后会慢慢改善,求各位大佬指教。