初试网络爬虫(1)

原创 2013年12月06日 12:05:37

        在上次的博文中提到,整个爬虫的一个整体流程现在就逐步来分析和实现我们的需求。

      第一。根据URL爬取响应的整个HTML页面。  第二。从HTML提取自己想要的东西。

着这是主要的也是最基本的思路,下面我们就把每个过程都细分下,把可能出现的问题都列出来。

               (1)URL的去重(已经爬过的URL,不在爬取第二次)      

               (2)返回的状态码分析。200、300、400、500等      

               (3)爬取内容的编码问题。      

               (4)爬取的内容包括:meta 、 head 、 body      

               (5)网页内容的去标签      

               (6)网页去噪并提取正文:包括广告,版权,特殊字符,导航等等。      

               (7)网页请求超时。      

               (8)网页的有效性。无效页面包括:空白页,登陆页,动态图片,欢迎页面等等      

               (9)确定网页采集的频率。哪些网页更新快,哪些网页更新慢。      

               (10)网页采集过快封号,封IP问题      

               (11)需要解决登录的网站      

这些问题是我们在做实现爬虫功能之前想到可能要遇到的问题,但是我们没必要先考虑这些问题,这是什么意思呢?

  因为url对应的html是各种各样的,我们在实现之前要想到可能出现的问题,(不一定全面,可能在实际过程中可能还会遇到新的问题,当遇到新的问题时,我们就要把这个新问题列入上面的问题中)列出这些问题我们为什么先不考虑呢,呵呵。这就是我提到的框架,先不要管什么问题,先把流程走通,也就是说先找到一些不是乱码的正规网页,不能登录,不存在任何问题的网页进行实验,若把整个流程都弄通过了那么整个思路就有了,然后在去解决上面一个一个的问题。

               网络爬虫,其实就是模仿浏览器去请求服务器。然后处理服务器响应的结果。

               既然要模仿浏览器去请求,而浏览器和服务器之间进行工作时要遵守一种协议,那就是HTTP协议,所以搞互联网的话和网络爬虫的话,必须的把HTTP网络协议铭记于心。

             为什么要学习HTTP呢,开始我也不懂什么是HTTP但是后来发现它的重要性,在你请求页面是,返回的状态嘛很重要,只有返回状态嘛是200的或者300(需要进行下处理)你才能去接受以及分析它的响应结果,这样1.可以防止不去处理那些由于服务器的原因响应失败或者错误页面。2.可以更好的处理你想要的结果,因为大家都知道服务器响应请求结果有很多类型。比如说纯HTML的文本格式,视频格式,图片等等,如果你只是想要纯文本的HTNL那么就不需要处理非HTML格式的响应结果。所以无论是互联网还是爬虫对HTTP协议的理解和认识非常重要。

       给大家介绍下一个博客详细的解释了HTTP协议的内容。写的很错了,建议大家仔细看看  http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html

      下面说下HttpClient这个工具包。http://hc.apache.org/httpclient-3.x/ 官网

       HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

     废话不多说,HTTP协议和HttpClient的介绍和详细内容网上都有,下面来例子(给大家介绍个httpclient的入门级出,自我感觉写的不错 http://www.ibm.com/developerworks/cn/opensource/os-httpclient/)

    

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.methods.GetMethod;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: ninja
 * Date: 11/5/13
 * Time: 12:43 PM
 * To change this template use File | Settings | File Templates.
 */
public class Spider {
    public static Map<String,String> getHTML(String url) {
        Map<String,String> map = new HashMap<String, String>(); 
        StringBuffer HTMLstr = new StringBuffer();
        String markCode = null; //响应编码,A表示是正常的。其他都表示有误
        String HTML = null; //响应结果HTML
        BufferedReader reader = null;
        HttpMethod get = null;
        try{

            HttpClient httpClient = new HttpClient(); // 创建对象

//            连接超时:
              // httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(1000); //请求超时处理,表示请求超时超过1秒这抛出异常
//            读取超时:
               httpClient.getHttpConnectionManager().getParams().setSoTimeout(3000);//响应超时处理,响应超过3000抛出异常

               get = new GetMethod(url); // get方法请求URL
               try {
                   httpClient.executeMethod(get);
               } catch (IOException e){
                   markCode = "B"; //"执行GET方法报IO错"
                   System.out.println("在执行GET方法时出错。。。。。。。。");
                  // e.printStackTrace();
               }
               //执行
               int code = get.getStatusCode();      //响应状态码
               StatusLine line = get.getStatusLine();
               System.out.println("响应状态:------ "  + line.toString());
               System.out.println("URL为:------" + url + "<begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
               if (code == 200) { // 响应为200时表示成功
                   String contentType = get.getResponseHeader("Content-Type").getValue();
                   if(contentType != null && !"".equals(contentType) && contentType.indexOf("text/html") != -1){
                       String reg_code = "<meta[^>]*?charset=[\"']?([0-9a-zA-Z-]+[\\W]*?)[\"']*[\\s*]?[/]?>";//编码的正则表达式
                       reader = new BufferedReader(new InputStreamReader(get.getResponseBodyAsStream(),"ISO-8859-1"));
                       String temp = null;
                       String encode = "UTF-8";
                       boolean flag = true;
                       while ((temp = reader.readLine()) != null){

                           if (flag){
                               Pattern p_code = Pattern.compile(
                                       reg_code, Pattern.CASE_INSENSITIVE);
                               Matcher m_code = p_code.matcher(temp);
                               while (m_code.find()) {
                                   encode = m_code.group(1);
                                   flag = false;
                               }
                           }

                           HTMLstr.append(temp + "\r\n");
                       }
                       if(HTMLstr.toString() != null && !"".equals(HTMLstr)){
                           markCode = "A";
                           HTML = new String(HTMLstr.toString().getBytes("ISO-8859-1"),encode);
                           map.put("HTML",HTML);
                       } else {
                           markCode = "F";
                           System.out.println("读出的页面是个空页面。。。。。。。。");
                       }
                   }  else{
                       markCode = "D"; //响应类型不属于text/html
                       System.out.println("响应类型不为text/html形式。。。。。。。。:" + contentType);
                   }
               } else{
                   markCode = "E"; //响应状态码不为200
                   System.out.println("响应状态码错误 : " + code);
               }
           }   catch (Exception e){
               markCode = "C"; //响应超时或者网络不好,以及其他BUG
               System.out.println("请求或者响应超时。。。。。。。。");
               //e.printStackTrace();
           }    finally {
               if(reader != null){
                   try {
                       reader.close();
                   } catch (Exception e){
                       e.printStackTrace();
                   }

               }
            if(get != null){
                get.releaseConnection();
            }
           }

           map.put("markCode",markCode);


       return map;
    }

    public static void main(String[] args){
        long a = System.currentTimeMillis();
        System.out.println(getHTML("http://3g.163.com/sports/13/1015/13/9B7VASNM00051CD5.html").toString());
        System.out.println(System.currentTimeMillis() - a);
    }
}

下篇博文我将重点结合上诉代码以及爬虫的问题跟大家分享下自己的思路的处理方案。可能讲的不好,也可能有问题,希望大家多多指教,我们共同进步。如果有什么想知道的或者对代码有疑问的地方等等问题,可以留言告诉我,也可以发邮件给我  zhouxiaoming2013@163.com

  

相关文章推荐

Python网络爬虫2 ---- scrapy爬虫架构介绍和初试

原文出处:http://my.oschina.net/dragonblog/blog/173290 上一篇文章的环境搭建是相对于手动操作的过程,而大家可能对这个疑问是什么是scrap...

异步网络爬虫的Python实现(1)

本文翻译自500L系列文章,原文链接, 原文作者A. Jesse Jiryu Davis 和 Guido van Rossum.A. Jesse Jiryu Davis是纽约MongoDB的一名工程师...

自己动手写网络爬虫源码part1

  • 2015年09月28日 19:50
  • 50MB
  • 下载

网络爬虫 学习1

作者:Ackarlix  随着网络的迅速发展,万维网成为大量信息的载体,如何有效地提取并利用这些信息成为一个巨大的挑战。搜索引擎(Search Engine),例如传统的通用搜索引擎AltaVi...
  • pandf
  • pandf
  • 2013年10月12日 16:32
  • 709

使用HttpClient实现网络爬虫 1

近期,听大神讲了一些分词的算法,深受启发,打算做一个互联网热词发现系统,主要由一个分布式网络爬虫和一个分词系统再加一个数据库构成,数据库这块还没有什么头绪,但是网络爬虫和分词算法都有些许眉目。于是打算...

python网络爬虫——基本概念及代码实现1

Python网络爬虫 爬虫是什么? 网络爬虫就是一段抓取网页的程序,基本操作就是抓取网页,每个网页都是有一段段代码组成的,爬虫的工作就是通过网页的链接地址寻找网页。   URI和URL的区别 Web上...

Linux企业级项目实践之网络爬虫(1)——项目概述及准备工作

我们在学习了Linux系统编程之后,需要一些实战项目来提高自己的水平,本系列我们通过编写一个爬虫程序,将我们学习的知识进行综合应用,同时在实现项目的过程中逐渐养成一些有用的思维方式,并具有初步的软件开...

Java网络爬虫crawler4j学习笔记<1>入门

简介 环境搭建 爬虫开发环境 代码研究环境 crawler4j架构 代码阅读与分析简介crawler4j是一个开源的网络爬虫框架(github地址),可以帮助我们很快地实现一个最基本的网络爬虫。同时由...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:初试网络爬虫(1)
举报原因:
原因补充:

(最多只允许输入30个字)