zoukankan      html  css  js  c++  java
  • Java爬虫

     1.网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成。传统爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统的一定停止条件。

      2.那么程序获取网页的原理到底是怎么回事呢?看下面的图:客服端首先向服务器端发出Http请求,之后服务器端返回相应的结果或者请求超时客户端自己报错。

      服务器端发出的Http请求,实际上说是对服务器的文件的请求。下面的表格是一些常见的HTTP请求对应的文件。(因为第一列给出的都是主机的网址信息,主机一般都通过配置文件将该请求转换为网站主页地址index.php或index.jsp或者index.html等)

    3.Java爬虫的代码实现

    1)dbcp.properties

    `########DBCP配置文件##########
    #驱动名
    driverClassName=com.mysql.jdbc.Driver
    #url
    url=jdbc:mysql://127.0.0.1:3306/peoper?useSSL=false
    #用户名
    username=root
    #密码
    password=sbj174615
    #初试连接数
    initialSize=30
    #最大活跃数
    maxTotal=30
    #最大idle数
    maxIdle=10
    #最小idle数
    minIdle=5
    #最长等待时间(毫秒)
    maxWaitMillis=1000
    #程序中的连接不使用后是否被连接池回收(该版本要使用removeAbandonedOnMaintenance和removeAbandonedOnBorrow)
    #removeAbandoned=true
    removeAbandonedOnMaintenance=true
    removeAbandonedOnBorrow=true
    #连接在所指定的秒数内未使用才会被删除(秒)(为配合测试程序才配置为1秒)
    removeAbandonedTimeout=1
    View Code

    2)DBCPUtil.java

    package com.j1702.db;
    
    import java.io.FileInputStream;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp2.BasicDataSourceFactory;
    
    
    
    
    
    /**
     * DBCP配置类
     * @author SUN
     */
    public class DBCPUtil {
         private static Properties properties = new Properties();
            private static DataSource dataSource;
            //加载DBCP配置文件
            static{
                try{
                    properties.load(DBCPUtil.class.getClassLoader().getResourceAsStream("dbcp.properties"));
                    dataSource = BasicDataSourceFactory.createDataSource(properties);
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        
        //从连接池中获取一个连接
        //从连接池中获取一个连接
        public static Connection getConnection(){
            Connection connection = null;
            try {
                connection = dataSource.getConnection();
                connection.setAutoCommit(false);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
        
    }
    View Code

    3)java爬虫

    package com.rimi.pachong;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.sql.Connection;
    
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import com.j1702.db.DBCPUtil;
     
    public class pachong1 {
        
        public static void main(String[] args) {
            pachong1 videoLinkGrab = new pachong1();
            videoLinkGrab.saveData("http://www.80s.tw/movie/list/q----");
        }
     
        /**
         * 将获取到的数据保存在数据库中
         * 
         * @param baseUrl
         *            爬虫起点
         * @return null
         * */
        public void saveData(String baseUrl) {
            Map<String, Boolean> oldMap = new LinkedHashMap<String, Boolean>(); // 存储链接-是否被遍历
     
            Map<String, String> videoLinkMap = new LinkedHashMap<String, String>(); // 视频下载链接
            String oldLinkHost = ""; // host
     
            Pattern p = Pattern.compile("(https?://)?[^/\s]*"); // 比如:http://www.zifangsky.cn
            Matcher m = p.matcher(baseUrl);
            if (m.find()) {
                oldLinkHost = m.group();
            }
     
            oldMap.put(baseUrl, false);
            videoLinkMap = crawlLinks(oldLinkHost, oldMap);
            
            // 遍历,然后将数据保存在数据库中
            try {
            
                Connection connection=DBCPUtil.getConnection();
                for (Map.Entry<String, String> mapping : videoLinkMap.entrySet()) {
                    String  sql ="insert into movie(MovieName,MovieLink) values(?,?)";
                    PreparedStatement ptmt =connection.prepareStatement(sql);
                    
                    ptmt.setString(1, mapping.getKey());
                    ptmt.setString(2, mapping.getValue());
                    ptmt.execute();
                    
                    connection.commit();
                //  System.out.println(mapping.getKey() + " : " + mapping.getValue());
                }
                
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
     
        /**
         * 抓取一个网站所有可以抓取的网页链接,在思路上使用了广度优先算法 对未遍历过的新链接不断发起GET请求, 一直到遍历完整个集合都没能发现新的链接
         * 则表示不能发现新的链接了,任务结束
         * 
         * 对一个链接发起请求时,对该网页用正则查找我们所需要的视频链接,找到后存入集合videoLinkMap
         * 
         * @param oldLinkHost
         *            域名,如:http://www.zifangsky.cn
         * @param oldMap
         *            待遍历的链接集合
         * 
         * @return 返回所有抓取到的视频下载链接集合
         * */
        private Map<String, String> crawlLinks(String oldLinkHost,
                Map<String, Boolean> oldMap) {
            Map<String, Boolean> newMap = new LinkedHashMap<String, Boolean>(); // 每次循环获取到的新链接
            Map<String, String> videoLinkMap = new LinkedHashMap<String, String>(); // 视频下载链接
            String oldLink = "";
     
            for (Map.Entry<String, Boolean> mapping : oldMap.entrySet()) {
                // System.out.println("link:" + mapping.getKey() + "--------check:"
                // + mapping.getValue());
                // 如果没有被遍历过
                if (!mapping.getValue()) {
                    oldLink = mapping.getKey();
                    // 发起GET请求
                    try {
                        URL url = new URL(oldLink);
                        HttpURLConnection connection = (HttpURLConnection) url
                                .openConnection();
                        connection.setRequestMethod("GET");
    //                    connection.setConnectTimeout(6000);
    //                    connection.setReadTimeout(6000);
     
                        if (connection.getResponseCode() == 200) {
                            InputStream inputStream = connection.getInputStream();
                            BufferedReader reader = new BufferedReader(
                                    new InputStreamReader(inputStream, "UTF-8"));
                            String line = "";
                            Pattern pattern = null;
                            Matcher matcher = null;
                            //电影详情页面,取出其中的视频下载链接,不继续深入抓取其他页面
                            if(isMoviePage(oldLink)){
                                boolean checkTitle = false;
                                String title = "";
                                while ((line = reader.readLine()) != null) {
                                    //取出页面中的视频标题
                                    if(!checkTitle){
                                        pattern = Pattern.compile("([^\s]+).*?</title>");
                                        matcher = pattern.matcher(line);
                                        if(matcher.find()){
                                            title = matcher.group(1);
                                            checkTitle = true;
                                            continue;
                                        }
                                    }
                                    // 取出页面中的视频下载链接
                                    pattern = Pattern
                                            .compile("(thunder:[^"]+).*thunder[rR]es[tT]itle="[^"]*"");
                                    matcher = pattern.matcher(line);
                                    if (matcher.find()) {
                                        videoLinkMap.put(title,matcher.group(1));
                                        System.out.println("视频名称: "
                                                + title + "  ------  视频链接:"
                                                + matcher.group(1));
                                        break;  //当前页面已经检测完毕
                                    }
                                }  
                            }
                            //电影列表页面
                            else if(checkUrl(oldLink)){
                                while ((line = reader.readLine()) != null) {
     
                                    pattern = Pattern
                                            .compile("<a href="([^"\s]*)"");
                                    matcher = pattern.matcher(line);
                                    while (matcher.find()) {
                                        String newLink = matcher.group(1).trim(); // 链接
                                        // 判断获取到的链接是否以http开头
                                        if (!newLink.startsWith("http")) {
                                            if (newLink.startsWith("/"))
                                                newLink = oldLinkHost + newLink;
                                            else
                                                newLink = oldLinkHost + "/" + newLink;
                                        }
                                        // 去除链接末尾的 /
                                        if (newLink.endsWith("/"))
                                            newLink = newLink.substring(0,
                                                    newLink.length() - 1);
                                        // 去重,并且丢弃其他网站的链接
                                        if (!oldMap.containsKey(newLink)
                                                && !newMap.containsKey(newLink)
                                                && (checkUrl(newLink) || isMoviePage(newLink))) {
                                            System.out.println("temp: " + newLink);
                                            newMap.put(newLink, false);
                                        }
                                    }
                                }
                            }
     
                            reader.close();
                            inputStream.close();
                        }
                        connection.disconnect();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
     
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    oldMap.replace(oldLink, false, true);
                }
            }
            // 有新链接,继续遍历
            if (!newMap.isEmpty()) {
                oldMap.putAll(newMap);
                videoLinkMap.putAll(crawlLinks(oldLinkHost, oldMap)); // 由于Map的特性,不会导致出现重复的键值对
            }
            return videoLinkMap;
        }
         
        /**
         * 判断是否是2015年的电影列表页面
         * @param url 待检查URL
         * @return 状态
         * */
        public boolean checkUrl(String url){
            Pattern pattern =  Pattern.compile("http://www.80s.tw/movie/list/q----\d*");
            Matcher matcher = pattern.matcher(url);
            if(matcher.find())
                return true;  //2015年的列表
            else
                return false;
        }
         
        /**
         * 判断页面是否是电影详情页面
         * @param url  页面链接
         * @return 状态
         * */
        public boolean isMoviePage(String url){
            Pattern pattern =  Pattern.compile("http://www.80s.tw/movie/\d+");
            Matcher matcher = pattern.matcher(url);
            if(matcher.find())
                return true;  //电影页面
            else 
                return false;
        }
         
    }
    View Code
  • 相关阅读:
    循环语句
    JAVA-数据类型、变量、常量
    JAVA——程序流程控制——循环语句——for循环(打印三角形)
    循环语句
    JAVA基础学习1
    新手上路
    mysql内置函数之事务
    mysql内置功能
    mysql内置函数之视图
    pymysql模块
  • 原文地址:https://www.cnblogs.com/sbj-dawn/p/7881860.html
Copyright © 2011-2022 走看看