zoukankan      html  css  js  c++  java
  • webmagic 二次开发爬虫 爬取网站图片

    webmagic的是一个无须配置、便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫。

    webmagic介绍 编写一个简单的爬虫

    webmagic的使用文档:http://webmagic.io/docs/

    webmagic的设计文档:webmagic的设计机制及原理-如何开发一个Java爬虫

    1.编写一个核心的url过滤类

     1 package com.xwer.spider.main;
     2 
     3 import java.util.List;
     4 
     5 import org.apache.log4j.Logger;
     6 
     7 import us.codecraft.webmagic.Page;
     8 import us.codecraft.webmagic.Site;
     9 import us.codecraft.webmagic.processor.PageProcessor;
    10 import us.codecraft.webmagic.utils.UrlUtils;
    11 
    12 /**
    13  * 定制爬虫逻辑的核心类
    14  * @author xwer
    15  *
    16  */
    17 public class MM_Processor implements PageProcessor {
    18     private Logger logger = Logger.getLogger(this.getClass());
    19     // 部分一:抓取网站的相关配置,包括编码、抓取间隔、重试次数等
    20     private Site site = Site.me().setRetryTimes(5).setSleepTime(1000);
    21     // 网页匹配规则
    22     private String urlPattern;
    23     public MM_Processor(String startUrl, String urlPattern) {
    24         // 设置所属域
    25         this.site = Site.me().setDomain(UrlUtils.getDomain(startUrl));
    26         this.urlPattern = urlPattern;
    27     }
    28 
    29     @Override
    30     // process是定制爬虫逻辑的核心接口,在这里编写抽取逻辑
    31     public void process(Page page) {
    32         site.setUserAgent("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
    33         //图片抓取规则
    34         String imgRegex3 = "http://mm.howkuai.com/wp-content/uploads/20[0-9]{2}[a-z]/[0-9]{2}/[0-9]{2}/[0-9]{1,4}.jpg";
    35         // 获取目标链接 例如 http://www.meizitu.com/a/5535.html
    36         List<String> requests = page.getHtml().links().regex(urlPattern).all();
    37         logger.info("获取到的目标链接是: "+requests);
    38         logger.info("添加链接( "+requests.size()+" )条到集合");
    39                   
    40          //将获取的链接存入到targetRequests中(list集合)
    41         page.addTargetRequests(requests);
    42         logger.info("队列中存储的链接数是: "+page.getResultItems().getAll().size());
    43         
    44         // 图片的title,标题名称,用于设定文件夹的名称 
    45          String imgHostFileName = page.getHtml().xpath("//title/text()").replace("\\p{Punct}", "").toString();
    46         logger.info("获取的标题是"+imgHostFileName);
    47         
    48         List<String> listProcess = page.getHtml().regex(imgRegex3).all();
    49         logger.info("存入的图片地址: "+listProcess);
    50         // 此处将标题一并抓取,之后提取出来作为文件名
    51         listProcess.add(0, imgHostFileName);
    52         logger.info("存入的图片链接数量是: "+listProcess.size());
    53         //将获取到的页面的数据放到resultItems集合中(map)
    54         page.putField("img", listProcess);
    55     }
    56     @Override
    57     public Site getSite() {
    58         return site;
    59     }
    60 }

    2.对获取的结果进行持久化处理

     1 package com.xwer.spider.main;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 import java.util.Map;
     6 import org.apache.log4j.Logger;
     7 import com.xwer.spider.utils.DownLoadUtils;
     8 import us.codecraft.webmagic.ResultItems;
     9 import us.codecraft.webmagic.Task;
    10 import us.codecraft.webmagic.pipeline.Pipeline;
    11 
    12 /**
    13  * 处理
    14  * @author xwer
    15  *
    16  */
    17 public class MM_Pipeline implements Pipeline {
    18     private Logger logger = Logger.getLogger(this.getClass());
    19     private String path;
    20 
    21     public MM_Pipeline() {
    22         setPath("/MM/");
    23     }
    24 
    25     public MM_Pipeline(String path) {
    26         setPath(path);
    27     }
    28 
    29     public void setPath(String path) {
    30         this.path = path;
    31     }
    32 
    33     // 处理下载的方法
    34     @Override
    35     public void process(ResultItems resultItems, Task task) {
    36         logger.info("到了process" + resultItems);
    37         String fileStorePath = this.path;
    38         for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
    39             if (entry.getValue() instanceof List) {
    40                 List<String> list = new ArrayList<String>((List) entry.getValue());    
    41                 //取出之前存的网页的标题,拼接成一个新的文件夹名称
    42                 fileStorePath = new StringBuffer(fileStorePath)
    43                                     .append(list.get(0))
    44                                     .append("\\").toString();
    45                 //遍历图片链接list
    46                 for (int i = 1; i < list.size(); i++) {
    47                     // 获取文件唯一名字
    48                     String realname = DownLoadUtils.subFileName(list.get(i));
    49                     String uuidname = DownLoadUtils.generateRandonFileName(realname);
    50                     // 这里通过自己写的下载工具前抓取到的图片网址,并放在对应的文件中
    51                     try {
    52                         DownLoadUtils.download(list.get(i), uuidname, fileStorePath);
    53                         logger.info("文件" + uuidname +"已经下载完毕");
    54                     } catch (Exception e) {
    55                         logger.warn("文件下载异常" + list.get(i));
    56                         e.printStackTrace();
    57                     }
    58                 }
    59             }
    60             else {
    61                 System.out.println(entry.getKey() + ":\t" + entry.getValue());
    62             }
    63         }
    64     }
    65 }

    3.编写一个下载图片的工具类

     1 package com.xwer.spider.utils;
     2 
     3 import java.io.File;
     4 import java.io.FileOutputStream;
     5 import java.io.InputStream;
     6 import java.io.OutputStream;
     7 import java.net.URL;
     8 import java.net.URLConnection;
     9 import java.util.UUID;
    10 
    11 /**
    12  * 下载相关的工具类
    13  * 
    14  * @author xwer
    15  *
    16  */
    17 public class DownLoadUtils {
    18 
    19     /**
    20      * 下载图片工具
    21      * 
    22      * @param urlString
    23      *            图片链接地址
    24      * @param filename
    25      *            图片的文件名字
    26      * @param savePath
    27      *            图片保存的路径
    28      * @throws Exception
    29      */
    30     public static void download(String urlString, String filename, String savePath) throws Exception {
    31         // 构造URL
    32         URL url = new URL(urlString);
    33         // 打开连接
    34         URLConnection con = url.openConnection();
    35         // 设置请求头
    36         con.addRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
    37         // 设置请求超时为5s
    38         con.setConnectTimeout(5 * 1000);
    39         // 输入流
    40         InputStream is = con.getInputStream();
    41 
    42         // 1K的数据缓冲
    43         byte[] bs = new byte[1024];
    44         // 读取到的数据长度
    45         int len;
    46         // 输出的文件流
    47         File sf = new File(savePath);
    48         if (!sf.exists()) {
    49             sf.mkdirs();
    50         }
    51         OutputStream os = new FileOutputStream(sf.getPath() + "\\" + filename);
    52         // 开始读取
    53         while ((len = is.read(bs)) != -1) {
    54             os.write(bs, 0, len);
    55         }
    56         // 完毕,关闭所有链接
    57         os.close();
    58         is.close();
    59     }
    60 
    61     /**
    62      * 截取真实文件名
    63      * 
    64      * @param fileName
    65      * @return
    66      */
    67     public static String subFileName(String fileName) {
    68         // 查找最后一个 \出现位置
    69         int index = fileName.lastIndexOf("\\");
    70         if (index == -1) {
    71             return fileName;
    72         }
    73         return fileName.substring(index + 1);
    74     }
    75 
    76     /**
    77      * 获得随机UUID文件名
    78      * 
    79      * @param fileName
    80      * @return
    81      */
    82     public static String generateRandonFileName(String fileName) {
    83         // 获得扩展名
    84         String ext = fileName.substring(fileName.lastIndexOf("."));
    85         return UUID.randomUUID().toString().replace("-", "") + ext;
    86     }
    87 }

    4.配置一个日志的输出文件(用户打印日志)

     1 ### direct log messages to stdout ###
     2 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
     3 log4j.appender.stdout.Target=System.out
     4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
     5 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
     6 
     7 ### direct messages to file mylog.log ###
     8 log4j.appender.file=org.apache.log4j.FileAppender
     9 log4j.appender.file.File=c:/mylog3.log
    10 log4j.appender.file.layout=org.apache.log4j.PatternLayout
    11 log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
    12 
    13 ### set log levels - for more verbose logging change 'info' to 'debug' ###
    14 log4j.rootLogger=info, stdout ,file

    5.编写程序的入口类

     1 package com.xwer.spider.main;
     2 
     3 import java.util.regex.Pattern;
     4 
     5 import org.junit.Test;
     6 
     7 
     8 
     9 import us.codecraft.webmagic.Spider;
    10 import us.codecraft.webmagic.scheduler.FileCacheQueueScheduler;
    11 
    12 public class MM_test {
    13     public static void main(String[] args) {
    14         //图片的存放路径,PiPline需要用到
    15         String fileStorePath = "D:\\test\\";
    16         
    17         //过滤网页的正则  http://www.meizitu.com/a/more_1.html
    18         String urlPattern = "http://www.meizitu.com/[a-z]/[0-9]{1,4}.html";
    19         //自定义的解析器核心
    20         MM_Processor mmSprider = new MM_Processor("http://www.meizitu.com/", urlPattern);
    21         
    22         //设置一些种子链接
    23         String[] urls ={"http://www.meizitu.com/",
    24                         "http://www.meizitu.com/a/4221.html",
    25                         "http://www.meizitu.com/a/4467.html",
    26                         "http://www.meizitu.com/a/5467.html",
    27                         "http://www.meizitu.com/a/5065.html",
    28                         "http://www.meizitu.com/a/4278.html",
    29                         "http://www.meizitu.com/a/699.html",
    30                         };
    31         //启动爬虫
    32         Spider.create(mmSprider).addUrl(urls)
    33                                 .setScheduler(new FileCacheQueueScheduler("D:\\webmagic\\cach"))
    34                                 .addPipeline(new MM_Pipeline(fileStorePath))
    35                                 .thread(10)
    36                                 .run();
    37     }
    38     
    39     
    40     

    6. 爬取结果

  • 相关阅读:
    deepin系统安装php扩展(或者统信UOS系统)
    前后端分离项目,访问后端接口跨域问题解决办法
    python打乱一个文件行数据
    python获取文件行数
    SQL进阶
    方便下载书籍网站
    gpuz软件下载
    U盘制作-安装win10系统
    docker -Docker安装FileBrowser实现网页版文件管理器
    OCP 063中文考试题库(cuug内部资料)第44题
  • 原文地址:https://www.cnblogs.com/xwer/p/7346416.html
Copyright © 2011-2022 走看看