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. linux 怎么查看系统的环境变量 与设置jdk 系统环境变量

    1.win 7 ,win10 怎么查看,添加系统环境的变量,大家都非常清楚的.但是linux 的 却不一定哦. 打开终端输入 :  “echo $PATH “ or  “export ”      如 ...

  2. Python基础—02-数据类型

    数据类型 存储单位 最小单位是bit,表示二进制的0或1,一般写作b 最小的存储单位是字节,用byte表示,1B = 8b 1024B = 1KB 1024KB = 1MB 1024MB = 1GB ...

  3. 搭建基本的React Native开发环境

    步骤如下: 1.安装HomeBrew,命令如下: 在终端输入命令:$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Home ...

  4. MySQL的数据类型(二)

    MySQL中提供了多种对字符数据的存储类型,不同的版本可能有所差异.以5.0版本为例,MySQL包括了CHAR.VARCHAR.BINARY.VARBINARY.BLOB.TEXT等多种字符串类型. ...

  5. mysql——查询重复数据,及删除重复数据只保留一条数据

    查询 text 表中,user_name字段值重复的数据及重复次数 select user_name,count(*) as count from text 删除 text 表中,重复出现的数据只保留 ...

  6. Python 2.6.6升级到Python2.7.15

    最近在使用Python处理MySQL数据库相关问题时,需要用到Python2.7.5及以上版本,而centos6.5等版本操作系统默认自带的版本为2.6.6,因此需要对python进行升级. Pyth ...

  7. Linux下编译出现undefined reference to ‘pthread_create’问题解决

    1.代码 /* * File: HeartPackageSendAgent.cpp * Author: Pangxiaojian * * * 主要实现:向服务器发送心跳包,每5s向服务器发送一个心跳包 ...

  8. zabbix监控MySQL服务状态

    Mysql模板使用 在zabbix_agent配置文件中加入监控配置 vim etc/zabbix_agentd.conf ... UserParameter=mysql.version,mysqla ...

  9. 初识python 函数(定义,传参,返回值)

    python基础(二): 菜鸟教程基础知识讲解的非常全面,内容选择我认为的重点输出一遍 函数: 定义一个函数: 你可以定义一个由自己想要功能的函数,以下是简单的规则: def fun(arg): pa ...

  10. Leecode刷题之旅-C语言/python-7.整数反转

    /* * @lc app=leetcode.cn id=7 lang=c * * [7] 整数反转 * * https://leetcode-cn.com/problems/reverse-integ ...