Java网络爬虫实操(4)

上一篇:Java网络爬虫实操(3)

本篇文章继续围绕NetDiscovery框架中pipeline的用法,结合另一个专门爬图片的框架PicCrawler,实现图片的批量下载和信息的存储。顺便介绍一下Vert.X框架中的mongo基础操作。

1) 目标任务

  • 找一个有很多美女图片的网址
  • 解析出要下载的图片链接,放到一个list中
  • 把list传到图片爬虫框架,几行代码搞定
  • 把需要的信息存储到mongodb
    //参考以前的文章,本篇要新增的依赖包
    implementation 'io.vertx:vertx-mongo-client:3.5.0'
    implementation 'com.cv4j.piccrawler:crawler:1.0.0'

2) 解析网页

目标网页
package com.sinkinka.parser;

import com.cv4j.netdiscovery.core.domain.Page;
import com.cv4j.netdiscovery.core.domain.ResultItems;
import com.cv4j.netdiscovery.core.parser.Parser;
import com.cv4j.netdiscovery.core.parser.selector.Selectable;

import java.util.ArrayList;
import java.util.List;

public class GirlParser implements Parser {

    @Override
    public void process(Page page) {

        String xpath = "//div[@class='contLeftA']/ul[@class='artCont cl']/li";
        List<Selectable> liList = page.getHtml().xpath(xpath).nodes();
        List<String> imgUrlList = new ArrayList<>();
        for(Selectable li : liList) {
            String imageUrl = li.xpath("//img/@src").get();
            imgUrlList.add(imageUrl);
        }

        ResultItems resultItems = page.getResultItems();
        resultItems.put("needDownloadImage", imgUrlList);
    }
}

3) 下载图片

package com.sinkinka.pipeline;

import com.cv4j.netdiscovery.core.domain.ResultItems;
import com.cv4j.netdiscovery.core.pipeline.Pipeline;
import com.cv4j.piccrawler.PicCrawlerClient;
import com.cv4j.piccrawler.download.strategy.FileGenType;
import com.cv4j.piccrawler.download.strategy.FileStrategy;

import java.util.List;

public class SaveGirlImage implements Pipeline {

    @Override
    public void process(ResultItems resultItems) {
        // 1.下载图片
        List<String> urls = resultItems.get("needDownloadImage");
        PicCrawlerClient.get()
                .timeOut(5000)
                .fileStrategy(new FileStrategy() {
                    @Override
                    public String filePath() {
                        return "temp";//保存图片的文件夹
                    }

                    @Override
                    public String picFormat() {
                        return "jpg";//保存图片的格式
                    }

                    @Override
                    public FileGenType genType() {
                        return FileGenType.AUTO_INCREMENT;//保存图片的文件名生成规则
                    }
                })
                .build()
                .autoReferer()       //自动设置refer
                .downloadPics(urls); //最关键的一行代码,把list扔进去就可以了

        //2. 设置信息给下一个pipeline SaveGirlImageLog使用
        resultItems.put("savecount", urls.size());
    }
}
批量下载到本地的图片

4) 保存信息

package com.sinkinka.pipeline;

import com.cv4j.netdiscovery.core.domain.ResultItems;
import com.cv4j.netdiscovery.core.pipeline.Pipeline;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.mongo.MongoClient;

import java.util.Date;

public class SaveGirlImageLog implements Pipeline {

    private MongoClient mongoClient;  //基于vertx的对象
    private String collectionName;

    public SaveGirlImageLog(MongoClient mongoClient, String collectionName){
        this.mongoClient = mongoClient;
        this.collectionName = collectionName;
    }

    @Override
    public void process(ResultItems resultItems) {
        //设置要保存的数据
        JsonObject jsonObject = new JsonObject();
        jsonObject.put("savecount", Integer.parseInt(resultItems.get("savecount").toString()));
        jsonObject.put("savetime", new Date().getTime());

        //1:存储到mongo数据库里
        mongoClient.save(collectionName, jsonObject, new Handler<AsyncResult<String>>() {
            @Override
            public void handle(AsyncResult<String> response) {
                if (response.succeeded()) {
                    System.out.println("save success, new id=" + response.result());
                } else {
                    System.out.println("save failure");
                    response.cause().printStackTrace();
                }
            }
        });

        //2:另一种lambda表达式的写法
//        mongoClient.save(collectionName, jsonObject, response -> {
//            if (response.succeeded()) {
//                System.out.println("save success, new id=" + response.result());
//            } else {
//                System.out.println("save failure");
//                response.cause().printStackTrace();
//            }
//        });
    }
}

存到mongo里的数据

5) 运行程序

  • 一个parser类GirlParser
  • 两个pipeline类SaveGirlImage、SaveGirlImageLog
  • Vert.X的MongoClient,异步非阻塞的方法
package com.sinkinka;

import com.cv4j.netdiscovery.core.Spider;
import com.sinkinka.parser.GirlParser;
import com.sinkinka.pipeline.SaveGirlImage;
import com.sinkinka.pipeline.SaveGirlImageLog;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.mongo.MongoClient;

public class GirlSpider {

    public static void main(String[] args) {
        String url = "http://www.woyaogexing.com/touxiang/nv/2018/586210.html";
        //创建一个vertx的mongoClient,SaveLog
        MongoClient mongoClient = MongoClient.createShared(Vertx.vertx(), getDatabaseConfig());
        
        Spider.create()
                .name("getGirlImage")
                .url(url)
                .parser(new GirlParser())
                .pipeline(new SaveGirlImage())
                .pipeline(new SaveGirlImageLog(mongoClient, "SaveLog"))
                .run();
    }

    public static JsonObject getDatabaseConfig() {
        JsonObject jsonObject = new JsonObject();
        jsonObject.put("connection_string", "mongodb://127.0.0.1:27017");
        jsonObject.put("db_name", "test");
//        jsonObject.put("username", "");
//        jsonObject.put("password", "");
        return jsonObject;
    }
}

6) 基于Vert.X的mongo操作

本篇的mongo操作使用的类是:io.vertx.ext.mongo.MongoClient
Vert.X的MongoClient提供的方法都是异步非阻塞的,非常灵活:

MongoClient

建议大家去了解一下增删改查,都有一个Handler<AsyncResult<[Type]>>
参考:http://vertx.io/docs/vertx-mongo-client/java/

7) 总结

利用框架我们能快捷的实现一个图片爬虫程序,本地有开发环境的话,几分钟就能搞定。以上例子仅仅是抛砖引玉,大家自由发挥其中的使用场景吧。

图片爬虫框架PicCrawler还有很多强大的用法,大家有兴趣可以去github上详细了解吧。

下一篇:Java网络爬虫实操(5)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,854评论 25 709
  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,788评论 1 180
  • 最近总能听见窗外有跑车的声音,也可能是内心对于跑车的向往,每个人都有一个不可一世的梦想吧……唯独对跑车有一种独特的...
    华美人阅读 248评论 0 2
  • 曾经如珠如宝,一夕之间世界颠覆。父母反目、骨肉分离,一个稚嫩的心灵该如何面对这场亲情的变故,走向成长之路?请关注短...
    幻小凡阅读 405评论 0 2
  • 〖碧落的大胆子〗 小时候,碧落同父母住在一条小街里面,街的两旁零零散散是些小店铺,街的后面有一片很大的...
    不做天煞孤星阅读 179评论 0 0