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

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

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

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

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

 package com.xwer.spider.main;

 import java.util.List;

 import org.apache.log4j.Logger;

 import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.utils.UrlUtils; /**
* 定制爬虫逻辑的核心类
* @author xwer
*
*/
public class MM_Processor implements PageProcessor {
private Logger logger = Logger.getLogger(this.getClass());
// 部分一:抓取网站的相关配置,包括编码、抓取间隔、重试次数等
private Site site = Site.me().setRetryTimes(5).setSleepTime(1000);
// 网页匹配规则
private String urlPattern;
public MM_Processor(String startUrl, String urlPattern) {
// 设置所属域
this.site = Site.me().setDomain(UrlUtils.getDomain(startUrl));
this.urlPattern = urlPattern;
} @Override
// process是定制爬虫逻辑的核心接口,在这里编写抽取逻辑
public void process(Page page) {
site.setUserAgent("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
//图片抓取规则
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";
// 获取目标链接 例如 http://www.meizitu.com/a/5535.html
List<String> requests = page.getHtml().links().regex(urlPattern).all();
logger.info("获取到的目标链接是: "+requests);
logger.info("添加链接( "+requests.size()+" )条到集合"); //将获取的链接存入到targetRequests中(list集合)
page.addTargetRequests(requests);
logger.info("队列中存储的链接数是: "+page.getResultItems().getAll().size()); // 图片的title,标题名称,用于设定文件夹的名称
String imgHostFileName = page.getHtml().xpath("//title/text()").replace("\\p{Punct}", "").toString();
logger.info("获取的标题是"+imgHostFileName); List<String> listProcess = page.getHtml().regex(imgRegex3).all();
logger.info("存入的图片地址: "+listProcess);
// 此处将标题一并抓取,之后提取出来作为文件名
listProcess.add(0, imgHostFileName);
logger.info("存入的图片链接数量是: "+listProcess.size());
//将获取到的页面的数据放到resultItems集合中(map)
page.putField("img", listProcess);
}
@Override
public Site getSite() {
return site;
}
}

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

 package com.xwer.spider.main;

 import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.xwer.spider.utils.DownLoadUtils;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline; /**
* 处理
* @author xwer
*
*/
public class MM_Pipeline implements Pipeline {
private Logger logger = Logger.getLogger(this.getClass());
private String path; public MM_Pipeline() {
setPath("/MM/");
} public MM_Pipeline(String path) {
setPath(path);
} public void setPath(String path) {
this.path = path;
} // 处理下载的方法
@Override
public void process(ResultItems resultItems, Task task) {
logger.info("到了process" + resultItems);
String fileStorePath = this.path;
for (Map.Entry<String, Object> entry : resultItems.getAll().entrySet()) {
if (entry.getValue() instanceof List) {
List<String> list = new ArrayList<String>((List) entry.getValue());
//取出之前存的网页的标题,拼接成一个新的文件夹名称
fileStorePath = new StringBuffer(fileStorePath)
.append(list.get(0))
.append("\\").toString();
//遍历图片链接list
for (int i = 1; i < list.size(); i++) {
// 获取文件唯一名字
String realname = DownLoadUtils.subFileName(list.get(i));
String uuidname = DownLoadUtils.generateRandonFileName(realname);
// 这里通过自己写的下载工具前抓取到的图片网址,并放在对应的文件中
try {
DownLoadUtils.download(list.get(i), uuidname, fileStorePath);
logger.info("文件" + uuidname +"已经下载完毕");
} catch (Exception e) {
logger.warn("文件下载异常" + list.get(i));
e.printStackTrace();
}
}
}
else {
System.out.println(entry.getKey() + ":\t" + entry.getValue());
}
}
}
}

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

 package com.xwer.spider.utils;

 import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID; /**
* 下载相关的工具类
*
* @author xwer
*
*/
public class DownLoadUtils { /**
* 下载图片工具
*
* @param urlString
* 图片链接地址
* @param filename
* 图片的文件名字
* @param savePath
* 图片保存的路径
* @throws Exception
*/
public static void download(String urlString, String filename, String savePath) throws Exception {
// 构造URL
URL url = new URL(urlString);
// 打开连接
URLConnection con = url.openConnection();
// 设置请求头
con.addRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)");
// 设置请求超时为5s
con.setConnectTimeout(5 * 1000);
// 输入流
InputStream is = con.getInputStream(); // 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
File sf = new File(savePath);
if (!sf.exists()) {
sf.mkdirs();
}
OutputStream os = new FileOutputStream(sf.getPath() + "\\" + filename);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 完毕,关闭所有链接
os.close();
is.close();
} /**
* 截取真实文件名
*
* @param fileName
* @return
*/
public static String subFileName(String fileName) {
// 查找最后一个 \出现位置
int index = fileName.lastIndexOf("\\");
if (index == -1) {
return fileName;
}
return fileName.substring(index + 1);
} /**
* 获得随机UUID文件名
*
* @param fileName
* @return
*/
public static String generateRandonFileName(String fileName) {
// 获得扩展名
String ext = fileName.substring(fileName.lastIndexOf("."));
return UUID.randomUUID().toString().replace("-", "") + ext;
}
}

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

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

5.编写程序的入口类

 package com.xwer.spider.main;

 import java.util.regex.Pattern;

 import org.junit.Test;

 import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.scheduler.FileCacheQueueScheduler; public class MM_test {
public static void main(String[] args) {
//图片的存放路径,PiPline需要用到
String fileStorePath = "D:\\test\\"; //过滤网页的正则 http://www.meizitu.com/a/more_1.html
String urlPattern = "http://www.meizitu.com/[a-z]/[0-9]{1,4}.html";
//自定义的解析器核心
MM_Processor mmSprider = new MM_Processor("http://www.meizitu.com/", urlPattern); //设置一些种子链接
String[] urls ={"http://www.meizitu.com/",
"http://www.meizitu.com/a/4221.html",
"http://www.meizitu.com/a/4467.html",
"http://www.meizitu.com/a/5467.html",
"http://www.meizitu.com/a/5065.html",
"http://www.meizitu.com/a/4278.html",
"http://www.meizitu.com/a/699.html",
};
//启动爬虫
Spider.create(mmSprider).addUrl(urls)
.setScheduler(new FileCacheQueueScheduler("D:\\webmagic\\cach"))
.addPipeline(new MM_Pipeline(fileStorePath))
.thread(10)
.run();
}

6. 爬取结果

webmagic 二次开发爬虫 爬取网站图片的更多相关文章

  1. node:爬虫爬取网页图片

    代码地址如下:http://www.demodashi.com/demo/13845.html 前言 周末自己在家闲着没事,刷着微信,玩着手机,发现自己的微信头像该换了,就去网上找了一下头像,看着图片 ...

  2. python爬虫-爬取百度图片

    python爬虫-爬取百度图片(转) #!/usr/bin/python# coding=utf-8# 作者 :Y0010026# 创建时间 :2018/12/16 16:16# 文件 :spider ...

  3. 如何使用robots禁止各大搜索引擎爬虫爬取网站

    ps:由于公司网站配置的测试环境被百度爬虫抓取,干扰了线上正常环境的使用,刚好看到每次搜索淘宝时,都会有一句由于robots.txt文件存在限制指令无法提供内容描述,于是便去学习了一波 1.原来一般来 ...

  4. Python:爬取网站图片并保存至本地

    Python:爬取网页图片并保存至本地 python3爬取网页中的图片到本地的过程如下: 1.爬取网页 2.获取图片地址 3.爬取图片内容并保存到本地 实例:爬取百度贴吧首页图片. 代码如下: imp ...

  5. 手把手教你用Node.js爬虫爬取网站数据

    个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! 开始之前请先确保自己安装了Node.js环境,还没有安装的的童鞋请自行百度 ...

  6. Java爬虫爬取网站电影下载链接

    之前有看过一段时间爬虫,了解了爬虫的原理,以及一些实现的方法,本项目完成于半年前,一直放在那里,现在和大家分享出来. 网络爬虫简单的原理就是把程序想象成为一个小虫子,一旦进去了一个大门,这个小虫子就像 ...

  7. Day11 (黑客成长日记) 爬取网站图片

    #导入第三方库# coding:utf-8import requests,re #找到需要爬取的网站'http://www.qqjia.com/sucai/sucai1210.htm' #1>获 ...

  8. python网络爬虫抓取网站图片

    本文介绍两种爬取方式: 1.正则表达式 2.bs4解析Html 以下为正则表达式爬虫,面向对象封装后的代码如下: import urllib.request # 用于下载图片 import os im ...

  9. 使用ajax爬取网站图片()

    以下内容转载自:https://www.makcyun.top/web_scraping_withpython4.html 文章关于网站使用Ajaxj技术加载页面数据,进行爬取讲的很详细 大致步骤如下 ...

随机推荐

  1. 虚拟局域网VLAN的配置实验

    实验涉及命令以及知识补充 交换机的不同状态 switch: :交换机的ROM态 rommon> :路由器的R状态 switch > :用户模式 switch# :特权模式 switch(c ...

  2. cornerstone提示“SQLite-database disk image is malformed”

    当点击workingCopy时错误如下 google了一下,有是有解决的办法,可是这些都是直接使用sqlite时产生的问题. sqlite错误 The database disk image is m ...

  3. spring mvc 数据绑定入门

    1:基本数据类型key 是必传的并且必须类型一致 // http://localhost:8080/bind/baseType.do?xage=10 @RequestMapping(value = & ...

  4. 寻找AP数

    题目背景 正整数n是无穷的,但其中有些数有神奇的性质,我们给它个名字--AP数. 题目描述 对于一个数字i是AP数的充要条件是所有比它小的数的因数个数都没有i的因数个数多.比如6的因数是1 2 3 6 ...

  5. leetcode笔记(五)809. Expressive Words

    题目描述 Sometimes people repeat letters to represent extra feeling, such as "hello" -> &qu ...

  6. Sql Server 查看存储过程最后修改时间

    Sql Server 查看存储过程最后修改时间 select * from sys.procedures order by modify_date desc

  7. 【c学习-13】

    /*库函数 1:数学函数库:math.h abs():绝对值; acos(),asin(),atan():cos,sin,tan的倒数 exp():指数的次幂 pow(x,y):x的y次幂 log() ...

  8. 微信小程序引用iconfont图标字体解决方案;

    1)首先,登录阿里巴巴iconfont.cn 2)新建项目 3)点击icon收藏 4)加入到test项目中   5)下载到本地解压   6)生成代码   7)复制iconfont.css到xxx.wx ...

  9. MySQL数据库操作(DDL)

    一.创建数据库 语法:create database 数据库名称 [库选项]; 库选项:(可选)数据库的属性,一般有字符集与校对集,保存在数据库所属文件夹下的opt文件 charset:字符集,表示该 ...

  10. 在一台Apache服务器上创建多个站点(不同域名)

    使用不同的域名来区分不同的网站,所有的域名解析都指向同一个 IP 地址.Apache通过在HTTP头中附带的 host参数来判断用户需要访问哪一个网站. 例如要在一台服务器上设置如下两个站点: htt ...