老李分享:网页爬虫java实现

老李分享:网页爬虫java实现

 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-84505200。

一. 设计思路

 

(1)一个收集所需网页全站或者指定子域名的链接队列

(2)一个存放将要访问的URL队列(跟上述有点重复, 用空间换时间, 提升爬取速度)

(3)一个保存已访问过URL的数据结构

 数据结构有了, 接下来就是算法了, 一般推荐采取广度优先的爬取算法, 免得中了反爬虫的某些循环无限深度的陷阱。

 使用了 jsoup (一个解析HTML元素的Lib)和 httpclient (网络请求包)来简化代码实现。

  

二. 代码实现

上述三种数据结构:

// 已爬取URL <URL, isAccess>
final static ConcurrentHashMap<String, Boolean> urlQueue = new ConcurrentHashMap<String, Boolean>();

// 待爬取URL
final static ConcurrentLinkedDeque<String> urlWaitingQueue = new ConcurrentLinkedDeque<String>();

// 待扫描网页URL队列
final static ConcurrentLinkedDeque<String> urlWaitingScanQueue = new ConcurrentLinkedDeque<String>();

入队等待:

/**

     * url store in the waiting queue

     * @param originalUrl

     * @throws Exception

     */

    private static void enterWaitingQueue(final String originalUrl) throws Exception{

 

        String url = urlWaitingScanQueue.poll();

 

        // if accessed, ignore the url

        /*while (urlQueue.containsKey(url)) {

            url = urlWaitingQueue.poll();

        }*/

 

        final String finalUrl = url;

 

        Thread.sleep(600);

 

        new Thread(new Runnable() {

 

            public void run() {

 

                try{

 

                    if (finalUrl != null) {

 

                        Connection conn = Jsoup.connect(finalUrl);

                        Document doc = conn.get();

 

                        //urlQueue.putIfAbsent(finalUrl, Boolean.TRUE); // accessed

 

                        logger.info("扫描网页URL: " + finalUrl);

 

                        Elements links = doc.select("a[href]");

 

                        for (int linkNum = 0; linkNum < links.size(); linkNum++) {

                            Element element = links.get(linkNum);

 

                            String suburl = element.attr("href");

 

                            // 某条件下, 并且原来没访问过

                            if (!urlQueue.containsKey(suburl)) {

 

                                    urlWaitingScanQueue.offer(suburl);

                                    urlWaitingQueue.offer(suburl);

                                    logger.info("URL入队等待" + linkNum + ": " + suburl);

                                }

                            }

 

                        }

 

                    }

 

                } catch (Exception ee) {

                    logger.error("muti thread executing error, url: " + finalUrl, ee);

                }

 

            }

        }).start();

    }


你可能感兴趣的:(测试)