webmagic+selenium+mongodb+springboot抓取JD商品信息

最近刚学了webmagic这么一个爬虫框架(之前都是手调api)于是决定写个demo,我就拿京东的商品来练练手。

一、采用的技术

webmagic:一个优秀开源的java爬虫框架,听说是根据python的scarpy的设计思想来写的,具体的思想大概就是抓取你想要爬的url放在队列中,主要是根据判断条件该url为列表页还是详情页,如果是列表页就爬取url放在队列中,如果从列表中拿到的url是详情页就解析想要的数据存储起来,这种思想就很适合并发执行去消费队列的url。底层默认是采用httpclient去抓取静态页面,因此解决不了js动态加载的问题,所以我们需要自己定制获取页面的方式,例如selenium,同时我们也可以自己定制存储数据的方式,例如mongodb,同时webmagic还有许多优秀的功能,重试机制,访问频率,代理ip设置,对比原生api减少了很多的代码量。

官方文档:http://webmagic.io/docs/zh/

selenium:selenium是一个测试驱动,最早是做测试用的,但是现在被拿来爬虫的居多,暴力抓取数据,模仿用户行为,可以解决其他爬虫api无法解决的问题,但是占用内存大,因为是一种有头浏览器,相当于你打开了一个浏览器去访问,这里使用selenium是因为京东部分数据是js动态解析,httpclient获取不到。

mongodb:一个文档型数据库,用来存储数据的好处是无需建表,不需要每次爬取不同类型数据都需要建表,同一张表中的数据可以不一样,集成spring中时使用mongoTempalte运用简单。

springboot: 使用springboot主要是为了集成mongodb,方便开发,并且使用springboot的单元测试

二、定制存储方式Pipeline

这里采用springboot集成mongodb的方法,需要配置mongodb

spring:
   data: 
     mongodb:
       host: 127.0.0.1
       database: test
@Slf4j
public class MongodbPipeline implements Pipeline {

    private MongoTemplate mongoTemplate;

    public MongodbPipeline () {
        //从spring获取MongoTemplate,这里需要一个获取spring容器bean的工具类
        this.mongoTemplate = (MongoTemplate) SpringApplicationContextHolder.getBean(MongoTemplate.class);
    }

    @Override
    public void process(ResultItems resultItems, Task task) {

        Map<String, Object> mapResults = resultItems.getAll();

        if (mapResults == null || mapResults.size() == 0) {
            return;
        }

        Iterator<Map.Entry<String, Object>> iter = mapResults.entrySet().iterator();

        Map.Entry<String, Object> entry;

        //document是一个key-value映射值的集合,包:org.bson.Document
        Document document = new Document();

        while (iter.hasNext()) {

            entry = iter.next();

            System.out.println();

            document.put(entry.getKey(),entry.getValue());

        }

        //插入数据
        mongoTemplate.insert(document, "jd_iphone11");

        log.info("插入一条数据成功");

    }
}

工具类:SpringApplicationContextHolder

@Component
public class SpringApplicationContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (com.bin.meishikecan.utils.SpringApplicationContextHolder.applicationContext == null) {
            com.bin.meishikecan.utils.SpringApplicationContextHolder.applicationContext = applicationContext;
        }
        System.out.println("---------------------------------------------------------------------");

        System.out.println("---------------------------------------------------------------------");

        System.out.println("---------------me.shijunjie.util.SpringUtil------------------------------------------------------");

        System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext=" + com.bin.meishikecan.utils.SpringApplicationContextHolder.applicationContext + "========");

        System.out.println("---------------------------------------------------------------------");
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

三、自定义JDPageProcessor

该类为webmagic的核心类,主要的业务逻辑解析在这里处理,包括列表页和详情页的解析。

public class JDPageProcessor implements PageProcessor {

    private Site site = Site.me().setRetryTimes(3).setSleepTime(3000).setUserAgent(
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");

    @Override
    public void process(Page page) {

        //正则匹配url是列表页还是详情列,列表页主要是获取一个页面中列表所有商品的详情页url,详情页为主要解析对象
        if (!page.getUrl().regex("https://item.jd.com/[0-9]+.html").match()) {

            //列表頁,addTargetRequests为新增在队列中,指url
            page.addTargetRequests(page.getHtml().xpath("//*[@id=\"J_goodsList\"]/ul/li/div[1]/div[1]/a/@href").all());

        } else {
            //详情页解析字段,主要使用xpath,具体语法可以网上搜
            page.putField("title",page.getHtml().xpath("//*[@class=\"sku-name\"]/text()").toString());
       page.putField("price",page.getHtml().xpath("/html/body/div[6]/div/div[2]/div[3]/div/div[1]/div[2]/span[1]/span[2]/text()").toString());
            page.putField("score",page.getHtml().xpath("//*[@id=\"comment-count\"]/a/text()").toString());
            page.putField("content",page.getHtml().getDocument().getElementsByClass("p-parameter").text());
            page.putField("url",page.getUrl().toString());
        }

    }

    @Override
    public Site getSite() {
        return site;
    }

四、selenium配置

1、想要使用selenium需要下载浏览器的驱动,这里采用谷歌的驱动:chromedriver

需要找到对应自己浏览器版本的chromedriver

下载地址:http://npm.taobao.org/mirrors/chromedriver/

2、需要配置config.ini(chrome的配置文件)

# What WebDriver to use for the tests
#driver=phantomjs
#driver=firefox
driver=chrome
#driver=http://localhost:8910
#driver=http://localhost:4444/wd/hub

# PhantomJS specific config (change according to your installation)
#phantomjs_exec_path=/Users/Bingo/bin/phantomjs-qt5
#phantomjs_exec_path=d:/phantomjs.exe
chrome_exec_path=C:\Program Files\Google\Chrome\Application\chrome.exe    //主要这里修改为你本地谷歌应用的路径
#phantomjs_driver_path=/Users/Bingo/Documents/workspace/webmagic/webmagic-selenium/src/main.js
#phantomjs_driver_loglevel=DEBUG
chrome_driver_loglevel=DEBUG

五、运行主程序

//spring的单元测试,相当于会启动springboot,因为要用到spring容器中的bean所以采用spring自带的单元测试
@SpringBootTest
public class ReptileTest {

    @Test
    void jdreplite() throws Exception {
       //加载配置文件
        System.setProperty("selenuim_config", "D:\\config.ini");
        Spider.create(new JDPageProcessor()).addUrl("https://search.jd.com/Search?keyword=iphone11&suggest=1.his.0.0&wq=iphone11&page=1&s=1&click=0")
                .setDownloader(new SeleniumDownloader("D:\\chromedriver.exe"))  //使用selenium并配置驱动
                .addPipeline(new MongodbPipeline())          //使用mongodb存储数据
                .addPipeline(new ConsolePipeline()).thread(1).run();   //同时打印到控制台,并可设置线程数
    }

}

六、运行结果

1、控制台打印

2、数据库保存

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值