java实现爬虫爬网站图片

第一步,实现 LinkQueue,对url进行过滤和存储的操作

import java.util.ArrayList;  
import java.util.Collections;  
import java.util.HashSet;  
import java.util.List;  
import java.util.Set;  
  
public class LinkQueue {  
  
   // 已访问的 url 集合  
    private static Set<String> visitedUrl = Collections.synchronizedSet(new HashSet<String>());

    // 未访问的url  
    private static List<String> unVisitedUrl = Collections.synchronizedList(new ArrayList<String>());

    // 未访问的URL出队列  
    public static String unVisitedUrlDeQueue() {
        if (unVisitedUrl.size() > 0) {
            String url = unVisitedUrl.remove(0);
            visitedUrl.add(url);
            return url;
        }
        return null;
    }

    // 新的url添加进来的时候进行验证,保证只是添加一次  
    public static void addUnvisitedUrl(String url) {
        if (url != null && !url.trim().equals("") && !visitedUrl.contains(url)
                && !unVisitedUrl.contains(url))
            unVisitedUrl.add(url);
    }

    // 判断未访问的URL队列中是否为空  
    public static boolean unVisitedUrlsEmpty() {
        return unVisitedUrl.isEmpty();
    }
      
}  

第二步,收集每一个url下的链接进行过滤产生新的链接

import java.util.HashSet;  
import java.util.Set;  
import org.htmlparser.Node;  
import org.htmlparser.NodeFilter;  
import org.htmlparser.Parser;  
import org.htmlparser.filters.NodeClassFilter;  
import org.htmlparser.filters.OrFilter;  
import org.htmlparser.tags.LinkTag;  
import org.htmlparser.util.NodeList;  
import org.htmlparser.util.ParserException;  
  
/** 
 * 过滤http的url,获取可以符合规则的url 
 * @author Administrator 
 * 
 */  
public class ParserHttpUrl {  
      
    // 获取一个网站上的链接,filter 用来过滤链接  
    public static Set<String> extracLinks(String url, LinkFilter filter) {  
        Set<String> links = new HashSet<String>();  
        try {  
            Parser parser = new Parser(url);  
            // 过滤 <frame >标签的 filter,用来提取 frame 标签里的 src 属性所表示的链接  
            NodeFilter frameFilter = new NodeFilter() {  
                public boolean accept(Node node) {  
                    if (node.getText().startsWith("frame src=")) {  
                        return true;  
                    } else {  
                        return false;  
                    }  
                }  
            };  
            // OrFilter 来设置过滤 <a> 标签,和 <frame> 标签  
            OrFilter linkFilter = new OrFilter(new NodeClassFilter(  
                    LinkTag.class), frameFilter);  
            // 得到所有经过过滤的标签  
            NodeList list = parser.extractAllNodesThatMatch(linkFilter);  
            for (int i = 0; i < list.size(); i++) {  
                Node tag = list.elementAt(i);  
                if (tag instanceof LinkTag)// <a> 标签  
                {  
                    LinkTag link = (LinkTag) tag;  
                    String linkUrl = link.getLink();// url  
                    if (filter.accept(linkUrl))  
                        links.add(linkUrl);  
                } else// <frame> 标签  
                {  
                    // 提取 frame 里 src 属性的链接如 <frame src="test.html"/>  
                    String frame = tag.getText();  
                    int start = frame.indexOf("src=");  
                    frame = frame.substring(start);  
                    int end = frame.indexOf(" ");  
                    if (end == -1)  
                        end = frame.indexOf(">");  
                    String frameUrl = frame.substring(5, end - 1);  
                    if (filter.accept(frameUrl))  
                        links.add(frameUrl);  
                }  
            }  
        } catch (ParserException e) {  
            e.printStackTrace();  
        }  
        return links;  
    }  
} 

第三步,实现图片下载功能

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.InputStream;  
import java.net.URL;  
import java.net.URLConnection;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.regex.Matcher;  
import java.util.regex.Pattern;  
  
/*** 
 * java抓取网络图片 
 *
 * @author swinglife 
 */  
public class DownLoadPic {  
  
    // 编码  
    private static final String ECODING = "UTF-8";  
    // 获取img标签正则  
    private static final String IMGURL_REG = "<img.*src=(.*?)[^>]*?>";  
    // 获取src路径的正则  
    private static final String IMGSRC_REG = "http:\"?(.*?)(\"|>|\\s+)";  
  
    public static void downloadPic(String url) {  
        // 获得html文本内容  
        String HTML = null;  
        try {  
            HTML = DownLoadPic.getHTML(url);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        if (null != HTML && !"".equals(HTML)) {  
            // 获取图片标签  
            List<String> imgUrl = DownLoadPic.getImageUrl(HTML);  
            // 获取图片src地址  
            List<String> imgSrc = DownLoadPic.getImageSrc(imgUrl);  
            // 下载图片  
            DownLoadPic.download(imgSrc);  
        }  
    }  
  
    /*** 
     * 获取HTML内容 
     *  
     * @param url 
     * @return 
     * @throws Exception 
     */  
    private static String getHTML(String url) throws Exception {  
        URL uri = new URL(url);  
        URLConnection connection = uri.openConnection();  
        InputStream in = connection.getInputStream();  
        byte[] buf = new byte[1024];  
        int length = 0;  
        StringBuffer sb = new StringBuffer();  
        while ((length = in.read(buf, 0, buf.length)) > 0) {  
            sb.append(new String(buf, ECODING));  
        }  
        in.close();  
        return sb.toString();  
    }  
  
    /*** 
     * 获取ImageUrl地址 
     *  
     * @param HTML 
     * @return 
     */  
    private static List<String> getImageUrl(String HTML) {  
        Matcher matcher = Pattern.compile(IMGURL_REG).matcher(HTML);  
        List<String> listImgUrl = new ArrayList<String>();  
        while (matcher.find()) {  
            listImgUrl.add(matcher.group());  
        }  
        return listImgUrl;  
    }  
  
    /*** 
     * 获取ImageSrc地址 
     *  
     * @param listImageUrl 
     * @return 
     */  
    private static List<String> getImageSrc(List<String> listImageUrl) {  
        List<String> listImgSrc = new ArrayList<String>();  
        for (String image : listImageUrl) {  
            Matcher matcher = Pattern.compile(IMGSRC_REG).matcher(image);  
            while (matcher.find()) {  
                listImgSrc.add(matcher.group().substring(0, matcher.group().length() - 1));  
            }  
        }  
        return listImgSrc;  
    }  
  
    /*** 
     * 下载图片 
     *  
     * @param listImgSrc 
     */  
    private static void download(List<String> listImgSrc) {  
  
        for (String url : listImgSrc) {  
            try {  
                String imageName = url.substring(url.lastIndexOf("/") + 1, url.length());
                URL uri = new URL(url);  
                InputStream in = uri.openStream();  
                FileOutputStream fo = new FileOutputStream(new File(imageName));  
                byte[] buf = new byte[1024];  
                int length = 0;  
                while ((length = in.read(buf, 0, buf.length)) != -1) {  
                    fo.write(buf, 0, length);  
                }  
                in.close();  
                fo.close();  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  

实在Filter接口,定义过滤接口:

public interface Filter { 
    public boolean accept(String url);  
}  

第四步,过滤规则的实现:

public class Crawler {  
  
    /** 
     * 抓取过程 
     *  
     * @return 
     * @param seeds 
     */  
    public void crawling(String url) { // 定义过滤器  
          
        Filter filter = new Filter() {  
            public boolean accept(String url) {  
                //这里过滤规则随需要爬的网站的规则进行改变,推荐使用正则实现,本人是爬豆瓣网站  
                if(url.indexOf("douban.com/group/topic") != -1 || url.indexOf("douban.com/group/haixiuzu/discussion?start") != -1 )  
                    return true;  
                else  
                    return false;  
            }  
        };  
        // 初始化 URL 队列  
        LinkQueue.addUnvisitedUrl(url);  
          
        // 循环条件,待抓取的链接不空  
        while (!LinkQueue.unVisitedUrlsEmpty()) {  
            // 队头URL出队列  
            String visitUrl = (String) LinkQueue.unVisitedUrlDeQueue();  
            if (visitUrl == null)  
                continue;  
              
            DownLoadPic.downloadPic(visitUrl);  
  
            // 提取出下载网页中的 URL  
            Set<String> links = ParserHttpUrl.extracLinks(visitUrl, filter);  
            // 新的未访问的 URL 入队  
            for (String link : links) {  
                LinkQueue.addUnvisitedUrl(link);  
            }  
        }  
    }  
  
    // main 方法入口  
    public static void main(String[] args) {  
        Crawler crawler = new Crawler();  
        crawler.crawling("http://www.douban.com/group/haixiuzu/discussion?start=0");  
    }  
}  

转载请注明原文地址:
http://blog.csdn.net/javaxiaojian/article/details/46680297

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 在此特此声明:一下所有链接均来自互联网,在此记录下我的查阅学习历程,感谢各位原创作者的无私奉献 ! 技术一点一点积...
    远航的移动开发历程阅读 10,810评论 12 197
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,615评论 4 59
  • 【美】Beverly Engel:《这不是你的错:如何治愈童年创伤》 看到这本书的名字第一时间想起电影《心灵捕手》...
    张腾云阅读 673评论 0 1
  • 能够生存下来的物种,并不是那些最强壮的,也不是那些最聪明的,而是那些对变化做出快速反应的。 ——达尔文
    柘榎阅读 215评论 0 0