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. 菜鸟笔记 -- Chapter 6.2.1 权限修饰符

    6.2.1  权限修饰符 面向对象的三大特性就有封装,封装隐藏了对象的属性和实现细节,仅对外提供公共访问方式,而这个访问方式就是由权限修饰符控制的.Java中的权限修饰符主要包括private.pub ...

  2. 优雅的QSignleton (五) 优雅地进行GameObject命名

      这段时间空调吹感冒了,休息了好久 ​ 本篇介绍QSingleton最重要的功能,是它让QSingleton称得上优雅.相关内容之前介绍过. 代码如下: MonoSingletonPath.cs n ...

  3. oracle中特殊字符替换

    replace语法: REPLACE(char,search_string,[replacement_string]) 在replace中,每个search_String 都会被replacement ...

  4. Hibernate知识点小结(四)--JPA

    一.jpa的简介和入门 JPA:Java Persistence API,接口规范    Hinernate内部为JPA规范提供实现        开发步骤(EntityManager):       ...

  5. Integer大小比较问题

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Integer ...

  6. Struts2进阶学习4

    Struts2进阶学习4 自定义拦截器的使用 核心配置文件 <?xml version="1.0" encoding="UTF-8"?> <! ...

  7. 快速玩转linux(3)

    Linux常用命令 软件操作命令 执行操作 命令 软件包管理器 yum 安装软件 yum install xxx 卸载软件 yum remove xxx 搜索软件 yum search xxx 清除缓 ...

  8. php判断某个数是素数的3种方法

    什么是素数? 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数.(注:1不是素数.) 方法一: 基本方法,——计数方法. $num = 7; $n = ...

  9. mysql-介绍

    1.mysql几个重要的文件 每个数据库新建后,会产生数据库文件夹,在该文件夹下每张表均对应以下三个文件: xx.frm  存放表结构 xx.MYD    存放表数据 xx.MYI 存放表索引 mys ...

  10. 一些斗鱼TV Web API [Some DouyuTv API]

    一些斗鱼TV Web API [Some DouyuTv API]   写在最前 去年TI5前开发了dotaonly.com,网站需要用到各个直播平台API.不像国外网站Twitch那样开放,都有现成 ...