文档章节

Java实现爬虫示例

CarlDing
 CarlDing
发布于 2018/04/05 11:37
字数 891
阅读 1536
收藏 0
package test;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 爬虫示例
 * @author dingzhen
 *
 */
public class URLDemo {
	//提取的数据存放到该目录下
    private static String savepath="f:/a/";
    //等待爬取的url
    private static List<String> allwaiturl=new ArrayList<String>();
    //爬取过的url
    private static Set<String> alloverurl=new HashSet<String>();
    //记录所有url的深度进行爬取判断
    private static Map<String,Integer> allurldepth=new HashMap<String, Integer>();
    //爬取得深度
    private static int maxdepth=2;
    //生命对象,帮助进行线程的等待操作
    private static Object obj=new Object();
    //记录总线程数5条
    private static int MAX_THREAD=5;
    public static void main(String args[]){
        //确定爬取的网页地址,此处为当当网首页上的图书分类进去的网页
        //网址为        http://book.dangdang.com/
//        String strurl="http://search.dangdang.com/?key=%BB%FA%D0%B5%B1%ED&act=input";
        String strurl="https://news.baidu.com/guoji";
        
        //workurl(strurl,1);
        addurl(strurl,0);
        for(int i=0;i<MAX_THREAD;i++){
            new URLDemo().new MyThread().start();
        }
    }
    /**
     * 网页数据爬取
     * @param strurl
     * @param depth
     */
    public static void workurl(String strurl,int depth){
        //判断当前url是否爬取过
        if(!(alloverurl.contains(strurl)||depth>maxdepth)){
            //检测线程是否执行
            System.out.println("当前执行:"+Thread.currentThread().getName()+" 爬取线程处理爬取:"+strurl);
        //建立url爬取核心对象
        try {
            URL url=new URL(strurl);
            //通过url建立与网页的连接
            URLConnection conn=url.openConnection();
            //通过链接取得网页返回的数据
            InputStream is=conn.getInputStream();
            
            //提取text类型的数据
            if(conn.getContentType().startsWith("text")){
                
            }
            System.out.println(conn.getContentEncoding());
            //一般按行读取网页数据,并进行内容分析
            //因此用BufferedReader和InputStreamReader把字节流转化为字符流的缓冲流
            //进行转换时,需要处理编码格式问题
            BufferedReader br=new BufferedReader(new InputStreamReader(is,"GB2312"));
        
            //按行读取并打印
            String line=null;
            //正则表达式的匹配规则提取该网页的链接
            Pattern p=Pattern.compile("<a .*href=.+</a>");
            //建立一个输出流,用于保存文件,文件名为执行时间,以防重复
            PrintWriter pw=new PrintWriter(new File(savepath+System.currentTimeMillis()+".txt"));
            
            while((line=br.readLine())!=null){
                //System.out.println(line);
                //编写正则,匹配超链接地址
                pw.println(line);
                Matcher m=p.matcher(line);
                while(m.find()){
                    String href=m.group();
                    //找到超链接地址并截取字符串
                    //有无引号
                    href=href.substring(href.indexOf("href="));
                    if(href.charAt(5)=='\"'){
                        href=href.substring(6);
                    }else{
                        href=href.substring(5);
                    }
                    //截取到引号或者空格或者到">"结束
                try{
                    href=href.substring(0,href.indexOf("\""));
                }catch(Exception e){
                    try{
                        href=href.substring(0,href.indexOf(" "));
                    }catch(Exception e1){
                        href=href.substring(0,href.indexOf(">"));
                    }
                }
                if(href.startsWith("http:")||href.startsWith("https:")){
                    /*
                    //输出该网页存在的链接
                    //System.out.println(href);
                    //将url地址放到队列中
                    allwaiturl.add(href);
                    allurldepth.put(href,depth+1);
                    */
                    //调用addurl方法
                    addurl(href,depth);
                        }
                
                    }
                
                }
            pw.close();
            br.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        //将当前url归列到alloverurl中        
        alloverurl.add(strurl);        
        System.out.println(strurl+"网页爬取完成,已爬取数量:"+alloverurl.size()+",剩余爬取数量:"+allwaiturl.size());
        }
        /*
        //用递归的方法继续爬取其他链接
        String nexturl=allwaiturl.get(0);
        allwaiturl.remove(0);
        workurl(nexturl,allurldepth.get(nexturl));
        */
        if(allwaiturl.size()>0){
            synchronized(obj){
                obj.notify();
            }
        }else{
            System.out.println("爬取结束.......");
        }
                
        }
    /**
     * 将获取的url放入等待队列中,同时判断是否已经放过
     * @param href
     * @param depth
     */
    public static synchronized void addurl(String href,int depth){
        //将url放到队列中
        allwaiturl.add(href);
        //判断url是否放过
        if(!allurldepth.containsKey(href)){
            allurldepth.put(href, depth+1);
        }
    }
    /**
     * 移除爬取完成的url,获取下一个未爬取得url
     * @return
     */
    public static synchronized String geturl(){
        String nexturl=allwaiturl.get(0);
        allwaiturl.remove(0);
        return nexturl;
    }
    /**
     * 线程分配任务
     */
    public class MyThread extends Thread{
        @Override
        public void run(){
            //设定一个死循环,让线程一直存在
            while(true){
                //判断是否新链接,有则获取
                if(allwaiturl.size()>0){
                    //获取url进行处理
                    String url=geturl();
                    //调用workurl方法爬取
                    workurl(url,allurldepth.get(url));
                }else{
                    System.out.println("当前线程准备就绪,等待连接爬取:"+this.getName());
                    //建立一个对象,让线程进入等待状态,即wait()
                    synchronized(obj){
                        try{
                            obj.wait();
                        }catch(Exception e){
                            
                        }
                    }
                }
            }
        }
        
    }
}

 

© 著作权归作者所有

CarlDing
粉丝 5
博文 106
码字总数 78103
作品 0
济南
其他
私信 提问
在 Hibernate 中直接操作 JDBC 接口

简介: Hibernate 在处理多表关联及分组排序等复杂数据库查询操作时,其固有的 O-R 映射机制会产生大量冗余 SQL 操作,系统性能比传统的 JDBC 低很多。本文分析了 Hibernate 产生此类问题的原...

红薯
2010/04/16
791
2
Java 13 新特性及实战案例

近期 Java 界好消息频传。先是 Java 13 发布,接着 Eclipse 也发布了新版本表示支持新版本的Java 特性。本文介绍了 Java 13 的新特性并展示了相关的示例。 2019年9月17日,Java 13 正式发布。...

waylau
09/23
465
4
如何以Java实现网页截图技术

今天看到某网友关于“如何以Java实现网页截图技术”的咨询帖,由于出现该咨询的地点非常不适合较长回复,故以博文形式回答。 事实上,如果您想以Java实现网页截图,也就是“输入一段网址,几...

Carl_
2015/03/03
310
7
基于 Python 的开源网络爬虫框架 - WebCollector-Python

WebCollector-Python WebCollector-Python 是一个无须配置、便于二次开发的 Python 爬虫框架(内核),它提供精简的的 API,只需少量代码即可实现一个功能强大的爬虫。 WebCollector Java版本...

CrawlScript
02/11
5.9K
9
微服务跨语言 gRPC 之 Java & Python

本文旨在说明 spring-boot-starter-grpc 框架与 Python 之间跨语言 RPC 调用的友好实现。阅读本文前,请详细阅读 wiki文档,以便了解 的工作原理。 Java Server & Client 模块说明: sample...

Anoyi
2018/09/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊nacos config的deleteConfig

序 本文主要研究一下nacos config的deleteConfig ConfigController nacos-1.1.3/config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigController.java @Controller@Re......

go4it
昨天
3
0
面试:原来Redis的五种数据类型底层结构是这样的

关注我,可以获取最新知识、经典面试题以及微服务技术分享   在Redis中会涉及很多数据结构,比如SDS,双向链表、字典、压缩列表、整数集合等等。Redis会基于这些数据结构自定义一个对象系统...

ccww_
昨天
4
0
java发送html模板的高逼格邮件

最近做了一个监测k8s服务pod水平伸缩发送邮件的功能(当pod的cpu/内存达到指定阈值后会水平扩展出多个pod、或者指定时间内pod数应扩展到指定数量),一开始写了个格式很low的邮件,像下面这样...

码农实战
昨天
10
0
php-fpm配置文件详解/MariaDB密码重置、慢查询日志

来源:https://blog.csdn.net/Powerful_Fy php-fpm主配置文件路径:/usr/local/php-fpm/etc/php-fpm.conf #位于安装php安装目录下的etc/目录中,该文件中最后一行将配置文件指向:include=/...

asnfuy
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部