webmagic 二次开发爬虫 爬取网站图片
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 二次开发爬虫 爬取网站图片的更多相关文章
- node:爬虫爬取网页图片
代码地址如下:http://www.demodashi.com/demo/13845.html 前言 周末自己在家闲着没事,刷着微信,玩着手机,发现自己的微信头像该换了,就去网上找了一下头像,看着图片 ...
- python爬虫-爬取百度图片
python爬虫-爬取百度图片(转) #!/usr/bin/python# coding=utf-8# 作者 :Y0010026# 创建时间 :2018/12/16 16:16# 文件 :spider ...
- 如何使用robots禁止各大搜索引擎爬虫爬取网站
ps:由于公司网站配置的测试环境被百度爬虫抓取,干扰了线上正常环境的使用,刚好看到每次搜索淘宝时,都会有一句由于robots.txt文件存在限制指令无法提供内容描述,于是便去学习了一波 1.原来一般来 ...
- Python:爬取网站图片并保存至本地
Python:爬取网页图片并保存至本地 python3爬取网页中的图片到本地的过程如下: 1.爬取网页 2.获取图片地址 3.爬取图片内容并保存到本地 实例:爬取百度贴吧首页图片. 代码如下: imp ...
- 手把手教你用Node.js爬虫爬取网站数据
个人网站 https://iiter.cn 程序员导航站 开业啦,欢迎各位观众姥爷赏脸参观,如有意见或建议希望能够不吝赐教! 开始之前请先确保自己安装了Node.js环境,还没有安装的的童鞋请自行百度 ...
- Java爬虫爬取网站电影下载链接
之前有看过一段时间爬虫,了解了爬虫的原理,以及一些实现的方法,本项目完成于半年前,一直放在那里,现在和大家分享出来. 网络爬虫简单的原理就是把程序想象成为一个小虫子,一旦进去了一个大门,这个小虫子就像 ...
- Day11 (黑客成长日记) 爬取网站图片
#导入第三方库# coding:utf-8import requests,re #找到需要爬取的网站'http://www.qqjia.com/sucai/sucai1210.htm' #1>获 ...
- python网络爬虫抓取网站图片
本文介绍两种爬取方式: 1.正则表达式 2.bs4解析Html 以下为正则表达式爬虫,面向对象封装后的代码如下: import urllib.request # 用于下载图片 import os im ...
- 使用ajax爬取网站图片()
以下内容转载自:https://www.makcyun.top/web_scraping_withpython4.html 文章关于网站使用Ajaxj技术加载页面数据,进行爬取讲的很详细 大致步骤如下 ...
随机推荐
- session和cookie的介绍
1.将cookie,session之前,还是先说说http协议 http协议是基于TCP/UDP之上的应用层一个标准 请求,响应的模式.是你必须先请求到一个服务端之后,服务端才会响应到你.他是不会无缘 ...
- 搜索框反射型xss问题解决(网站开发)
什么是反射型XSS XSS又叫CSS (Cross Site Script) ,跨站脚本攻击.它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的h ...
- C++ push方法与push_back方法
[转载他人的文章,下午在搞c++,谢谢共享] [摘要] push与push_back是STL中常见的方法,都是向数据结构中添加元素.初识STL,对于添加元素的方法以产生混淆,这里暂对两种方法作出比较分 ...
- c/c++面试总结---c语言基础算法总结2
c/c++面试总结---c语言基础算法总结2 算法是程序设计的灵魂,好的程序一定是根据合适的算法编程完成的.所有面试过程中重点在考察应聘者基础算法的掌握程度. 上一篇讲解了5中基础的算法,需要在面试之 ...
- vue项目苹果微信端使用this.$router.go(-1)返回上一页,上一页并不会重新加载的问题
window.addEventListener('pageshow', function(e) { // 通过persisted属性判断是否存在 BF Cache if (e.persisted) { ...
- 【ospf-路由聚合】
- C#正则表达式Regex类的使用
C#中为正则表达式的使用提供了非常强大的功能,这就是Regex类.这个包包含于System.Text.RegularExpressions命名空间下面,而这个命名空间所在DLL基本上在所有的项目模板中 ...
- ruby 第三方模块unirest使用
Creating Requests require 'unirest' response = Unirest.post 'http://httpbin.org/post', headers:{ Acc ...
- 【struts2】struts2的使用
1.使用步骤 1) 导入struts2的支持jar包 名称 说明 struts2-core-2.3.4.1.jar Structs2的核心类库 xwork-core-2.3.4.1.jar xwork ...
- Mult
public class MULT { public static void main(String args[]) { int k; for(int x=1;x<=9;x++) { for(i ...