基于webmagic爬虫实现网站图片下载


要使用webmagic爬虫首先要对该框架有一定了解,以下链接是webmagic的详细介绍和入门手册

webmagic中文手册

WebMagic分为四个组件部分

  • 1.Downloader
    负责从互联网上下载页面,一般不用配置
  • 2.PageProcessor
    负责解析页面,抽取有用信息,以及发现新的链接。是我们业务实现的主要核心部件
  • 3.Scheduler
  • 4.Pipeline
    负责对页面抽取到的结果和链接进行处理

pom.xml文件所需依赖

 <dependencies>
        <dependency>
            <groupId>us.codecraft</groupId>
            <artifactId>webmagic-core</artifactId>
            <version>0.7.3</version>
        </dependency>
        <dependency>
            <groupId>us.codecraft</groupId>
            <artifactId>webmagic-extension</artifactId>
            <version>0.7.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>us.codecraft</groupId>
            <artifactId>webmagic-selenium</artifactId>
            <version>0.7.3</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-chrome-driver -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-chrome-driver</artifactId>
            <version>3.141.59</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-server</artifactId>
            <version>3.141.59</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

ImagePageProcessor

为了实现网站爬虫,我们实现pageprocessor接口对代码进行扩展

public class ImagePageProcessor  implements PageProcessor {


    @Override
    public void process(Page page) {
    
        /* 第一步,从当前页面中发现指定格式链接添加进目标用来进行下一步爬取 */
        page.addTargetRequests(page.getHtml().links().regex("https://www\\.****\\.com/.*\\.html").all());
        
        /* 第二步,从当前页面爬取数据 */
        
        // 获取title标题(使用xpah获取指定数据) 
        String title=page.getHtml().xpath("//h1[@class='title']/text()").toString();
        
        // 判断是否有标题,无标题跳过当前页 
       if (StringUtils.isEmpty(title)) {
       
            // 跳过当前页,pipeline不会进行输出 
            page.setSkip(true);
        }
        
        //页面title装入page中的resultItems
        page.putField("title", title);
        
        //页面中得到指定位置的照片url,即img元素的src属性(使用xpah获取指定数据)
        List<String> PicUrl = page.getHtml().xpath("//div[@class='image']/p/span").css("img", "src").all();
        //另一种写法
        //List<String> PicUrl = page.getHtml().xpath("//div[@class='image']/p/span/img/@src").all();
        
        //照片路径装入page中的resultItems
        page.putField("PicUrl",PicUrl);
        
		// console打印当前页面全部内容(测试时用)
        //System.out.println(page.getHtml().toString()); 
    }

    @Override
    public Site getSite() {
        return Site.me().setRetryTimes(1).setSleepTime(2000);
    }

	//程序执行主程序入口
    public static void main(String[] args) {
    
        // 当需要使用seleniudownloader类时,加载webmaigc定义的属性参数,自定义指定路径
        System.getProperties().setProperty("selenuim_config","E:\\***\\src\\main\\resources\\config.ini");
        //spider创建ImagePageProcessor核心对象
        Spider.create(new ImagePageProcessor())
                //填写带照片的目标网址
                .addUrl("https://www.****.com/***/***.html")
                //实现console打印page中加入的resultItems元素
                .addPipeline(new ConsolePipeline())
                
                /*实现自定义ImagePiple打印page中加入的resultItems元素
                 *保存至E:\\spider文件下
                 */
                .addPipeline(new ImagePipeline("E:\\spider"))
                
                //一般不配置,不使用
                //.setScheduler(new QueueScheduler())
                
                //设置浏览器核心,当网页使用动态加载图片时需要配置seleniumDownloader
                .setDownloader(new SeleniumDownloader("E:\\***\\src\\main\\resources\\chromedriver.exe"))
                //设置线程数
                .thread(2)
                .run();

    }
    /**
     *SeleniumDownloader功能测试
     *该代码使用的是chrome浏览器,chromedriver百度自行下载
     *chrome和chromedriver版本保持严格匹配,我因为用错版本一直报错
     */
    @Test
    public void test2(){
        System.setProperty("webdriver.chrome.driver",
                "E:\\***\\src\\main\\resources\\chromedriver.exe");
        // 第二步:初始化驱动
        WebDriver driver = new ChromeDriver();
        // 第三步:获取目标网页
        driver.get("https://blog.csdn.net/qqzjyywx1/article/details/107702834");
        // 第四步:解析。以下就可以进行解了。使用webMagic等进行必要的解析。
        System.out.println("Page title is: " + driver.getTitle());
        System.out.println("Page title is: " + driver.getPageSource());

    }
}

ImagePipeline

接下来是执行文件保存功能的ImagePipeline,继承了FilePersistentBase类,实现了Pipeline接口

public class ImagePipeline extends FilePersistentBase implements Pipeline{
    private Logger logger = LoggerFactory.getLogger(getClass());
    //文件保存路径,之后配置
    String savepath=null;

	
    /**
     * create a default path"/data/webmagic/"
     */
    public ImagePipeline() {
        setPath("/data/webmagic/");
    }
	
    public ImagePipeline(String path) {
        setPath(path);
    }

    @Override
    public void process(ResultItems resultItems, Task task) {
    	//保存路径我设置为  自定义路径/网站名/标题名/文件名.png
        savepath = this.path+task.getUUID()+PATH_SEPERATOR+resultItems.get("title")+ PATH_SEPERATOR;

        List<String> PicUrl=resultItems.get("PicUrl");
       	// 当图片链接存在,生成savepath路径的文件夹,然后下载图片
        if(PicUrl.size()>0) {
            checkAndMakeParentDirecotry(savepath);
            downloadPicture(PicUrl);
        }else{
        //当图片链接不存在
            System.out.println("该page图片链接不存在:" + resultItems.get("title"));
        }

    }
    
	//下载图片链接方法代码
    public void downloadPicture(List<String> urlList) {
        URL url = null;
        for (int i = 0; i < urlList.size(); i++) {
            try {
                String[] files = urlList.get(i).split("/");
                String name = files[files.length - 1];
                url = new URL(urlList.get(i));

                File file = new File(savepath + name);
                // 文件不存在
                if(!file.exists()){

                    DataInputStream dataInputStream = new DataInputStream(url.openStream());
                    FileOutputStream fileOutputStream = new FileOutputStream(file);

                    byte[] buffer = new byte[1024 * 50];
                    int length;

                    while ((length = dataInputStream.read(buffer)) > 0) {
                        fileOutputStream.write(buffer, 0, length);
                    }
                    System.out.println("已经下载:" + savepath + name);
                    dataInputStream.close();
                    fileOutputStream.close();
                }else{
                    System.out.println("该文件已存在" + savepath + name);
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                System.out.println("下载文件路径不存在:" + url);
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

SeleniumDownloader

当网站没有动态数据,不使用
接下来是seleniumDownloader的config.ini文件配置,从GitHub上下载config.ini的源文件,配置相应的浏览器driver即可

# 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=/Users/Bingo/Downloads/phantomjs-1.9.8-macosx/bin/phantomjs
#phantomjs_driver_path=/Users/Bingo/Documents/workspace/webmagic/webmagic-selenium/src/main.js
#phantomjs_driver_loglevel=DEBUG

执行ImagePageProcessor中test2方法,出现下图则配置正确
在这里插入图片描述

执行代码

最后执行main方法,实现图片下载
在这里插入图片描述
就是上图这种效果

referer防盗链

在对新的网站下载图片时,发现下载的都是同一张图,经过对图片的request请求查看,发现多了一个referer的请求header,据此便可知该网站使用了防盗链技术防止图片被盗,那我们该怎么办呢?

前文中imagePipeline中我们使用

 DataInputStream dataInputStream = new DataInputStream(url.openStream());

直接通过url获取图片流信息现在已经是不可以了,需要通过url打开urlConnection,在connection中添加请求头信息,请求header信息可以通过打开浏览器查看图片请求得到,具体代码如下

UrlConnection urlConnection=url.openConnection()
urlConnection.setRequestProperty("referer","xxxurl");
DataInputStream dataInputStream = new DataInputStream(urlConnection.getInputStream());

希望大家能有所收获,谢谢大家

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值