各位大哥,小弟在这求救了……首先我说下我自己写的网络爬虫思想:1.首先,得到一个URL,截取重要字段如:“http://www.163.com” 我截取:“163.com”部分。2.其次,根据第1个步骤得到的URL,系统分配一个线程给它,然后根据URL去攫取有用的网址,进一步去爬取网络信息。3.最后,根据攫取的信息,分析内容,截取重要内容保存数据库中。问题如下:请问上面的思想有什么问题没有呢?各位大哥,在第2步中,每一个URL都是分配一个线程,然后在一个线程下,又发现新的URL,继续用本线程去爬取,可有会问题?当线程启动多了,发现如果只是启动一个线程会爬取很多的信息,如果是启动多个线程,发现爬取的信息就少了,请部这个是什么问题呢?如何解决当前各大网站字符编码的问题?因为当前的各大网站启用的编码不标准,没有通用的,有的使用UTF-8,有的使用GBK2312,等等。如何解决爬行数据乱码问题?在网站的后台,如何停止正在爬行数据的线程?
下面是图片截图:

解决方案 »

  1.   

    请问上面的思想有什么问题没有呢?各位大哥,在第2步中,每一个URL都是分配一个线程,然后在一个线程下,又发现新的URL,继续用本线程去爬取,可有会问题?
    你的cpu会爆掉,可以采用队列的方式处理,发现一个连接 把连接加入队列里面去...然后开固定数目的线程,去队列中取数据...
    如何解决当前各大网站字符编码的问题?因为当前的各大网站启用的编码不标准,没有通用的,有的使用UTF-8,有的使用GBK2312,等等。如何解决爬行数据乱码问题?
    有一个工具 可以 自动分析页面的编码,我忘记了,是根据页面流来处理的,还可以分析页面上是否有"gbk""utf-8""gb2312"等字样来确认
      

  2.   

    使用html-parser几乎最有效的,使用其中的工具类分析<meta>头部信息得到相关编码。然后分析<a>标签包含链接(可能有多个),随后进行递归就可以。具体html-parser使用方法还有有很多技巧:http://htmlparser.sourceforge.net
      

  3.   

    使用html-parser几乎最有效的,使用其中的工具类分析<meta>头部信息得到相关编码。然后分析<a>标签包含链接(可能有多个),随后进行递归就可以。具体html-parser使用方法还有有很多技巧:http://htmlparser.sourceforge.net
      

  4.   

    我告诉你我的方法,其实最简单的方法是不要采取一个URL一个线程,而是把所有解析出来的URL都放到一个队列里。而固定数量的工作线程就负责从这个队列里不停取URL并下载解析把新的URL再次放进去。
    另外涉及到一个线程排重的问题,我用的B-树的数据结构,而berkely db嵌入式数据库也用的这个数据结构,所以我就直接用了他,性能跟自己写的纯粹为排重设计的红黑树或者B-树分毫不差。当年我做了一个,还有架构图。主要的关键点:URL队列,排重,线程池。
    另外编码问题,我的方式是直接下载下来,如果HTTP头里有编码信息就直接用,如果没有,就先按照任意编码解码,也许里面中文会是乱码,但是<mata encode="gb2312"/>这一类的html里的编码信息是英文和数字,是不会乱码的,你用htmlparser一类的解析器把它解析出来,再重新解码一次就能得到正确的String了
      

  5.   

    楼主还要注意一点,需要过滤内容重复的页面,而对于这类页面,楼主需要把页面的内容解析为一个个的token来分析。这里需要楼主设计一个树结构,以便快速的过滤重复页面。
      

  6.   

    请问上面的思想有什么问题没有呢?各位大哥,在第2步中,每一个URL都是分配一个线程,然后在一个线程下,又发现新的URL,继续用本线程去爬取,可有会问题?[color=#008000]最好用队列或者堆栈来处理,如果见一个分一个线程的话CPU迟早要挂掉,建议用JAVA自带的线程池来处理当线程启动多了,发现如果只是启动一个线程会爬取很多的信息,如果是启动多个线程,发现爬取的信息就少了,请部这个是什么问题呢?可能和你写的代码有关系如何解决当前各大网站字符编码的问题?因为当前的各大网站启用的编码不标准,没有通用的,有的使用UTF-8,有的使用GBK2312,等等。如何解决爬行数据乱码问题?与服务器第一次握手后,就可以获取到页面的一些信息就包含有页面的编码信息,
       HttpURLConnection http;
       ....略...
       http = (HttpURLConnection) url.openConnection();
       ....略...   String charsets = "GBK";

       Map m = http.getHeaderFields();
       String contentType = m.get("Content-Type").toString().toLowerCase();
    if(contentType.indexOf("utf")>-1){
    charsets = "UTF-8";
    }InputStream httpInputStream = http.getInputStream();
    BufferedReader httpBufferedReader = new BufferedReader(new InputStreamReader(httpInputStream,charsets));....略...
    在网站的后台,如何停止正在爬行数据的线程?
    强制终止线程[/color]
      

  7.   

    正则表达式提取信息,我前段时间做了个小型的Web信息提取器
      

  8.   

    ........................................然后根据URL去攫取有用的网址,进一步去爬取网络信息。3.最后,根据攫取的信息,分析内容,截取重要内容...........................................如何"攫取",用的什么算法,锚文本是如何分析的,模式分类算法有没有?另外网络拓扑的概念呢?什么样的URL重要,什么样的不重要,链进链出的URL怎么分类统计的.....--------------------爬虫....
      

  9.   

    首先要理清思路,理清了也简单了。要有一个任务表来辅助实现队列功能,她记录记下几点内容:采集的网址(唯一,内容不能重复),状态位(1为已经采集内容,0为没有采集内容,默认为 0)有了这个小表,以后就简单了,程序只来做两件事情。
    第一件事情,就是从表中取一条状态位为 0 记录,然后下载内容到本地,然后把这条网址的状态位标志为1。(如果表为空,你就相当于{http://www.163.com,0})
    第二件事情就是分析一下刚下载的内容,用正则也好,别的方法也好,分析出来里面所有有用的 URL ,然后保存到任务表中(状态位为0),当然这个表里面的网址是不能重复的,你要保存之前先查一下里面有没有。
    所以只要一个循环让程序去做这两件事就可以了 ,循环中不断去检测一个标志,如果标志为停止则停止循环。如下,不是标准语言:
    int runFlag = 1;while (runFlag) {    int runFlag = file_get_contents("./run.lock"); // (从文件中读取一个数据,这个数据就是停止信号。当然可以是保存在文件中,也可以是数据库中,设置 内存中,memcache 中,总之能读到的地方,你可以设置这个数值为 false 来终止程序)    url = readFromDB(); //从数据库中取一条没有下载的 URL    contents = downloadFromUrl(url); // 下载内容    if (getCharsetOfContents(contents) == "GBK") {    // 检查下编码是不是你要的编码,不是,转
             contents = iconv("GKB", "UTF-8", contents);
        }    saveContents(contents); // 保存内容    urlsFromContents = preg_match_all(contents); // 从下载内容中取所有的 URL,    foreach (urlsFromContents as k => v) {    //  入库 URL
            if (checkExistsUrl($v)) {
                insertToDB($v);
            } 
        }
      

  10.   

    支持一楼的,补充一点,建议看看Heretrix,这个对你有帮助的,Heretrix就死使用队列加线程池的。
    对于编码问题,可以先分析meta标签来获得,然后在用获得的字符集去转换网页文件。网页文件解析可以使用HTML Parser库。
      

  11.   

    所谓的htmlparser已经过时了 本身的瓶颈问题已经使人用起来很恼火
    推荐使用jsoup 可以直接从网页抓取任意标签内的信息
    有些网站的编码很乱 例如 天涯 强力BS
      

  12.   

    建议你看这本书,当年我就是看的这本书,网络机器人Java编程指南,虽然本身书写得不是太好,但刚好很符合这个题目。
      

  13.   

    将所有URL放在队列中?需要考虑内存够不够的问题。需要视情况进行内外存数据的互换。
    编码问题可以用cpdetector。。(名字差不多吧)这个包,但用了它效率肯定不好。建议自己分析,没必要每个网页都分析正确无误,大部分正确就可以了。
    用不用线程池无关紧要。开固定数目的线程死循环抓取,不比线程池效率差,还可以省掉管理线程池的开销。
    注意线程间的数据同步。
    设计一个URL过滤器,可以实现许多实用的功能。
    BerkeyDB数据库不错.但如果你要抓取的URL在亿级以上的话,还是有效率问题。
    html-parser这东东就不必用了。非要用的话,可以自己把里面的关键部分拿出来,自己写个处理类。
    可以考虑异步IO的方式去获取数据,(JAVA-NIO),可能会有一点效率的提升,但需要你学会用。(新的HttpClient里面似乎有这功能)。结束爬行?结束线程就可以了 。怎么结束线程就不是爬虫的问题,是java的问题了。
    请注意使用volatile关键字。
      

  14.   

    我觉得楼主为每一个url都开一个线程有点浪费。你可以先开好60个线程作为slave,用于抓取网页,解析url,然后开设一个线程作为master,用于管理和分配url。这种模式也可以用于分布式的爬虫。
      

  15.   

    网页的深度需要考虑,而且爬过的链接需记录,要不会进入一个死循环,
    编码问题可以分析<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    这个可以用htmlparser来解决
      

  16.   

    另外,检测编码可以用一个工具:icu4j。这里有使用方法:http://blog.csdn.net/telnetor/archive/2010/02/06/5555349.aspx
      

  17.   

    个人建议,楼主可以尝试尝试分布式。当然具体的任务分配机制是需要事先考虑好的。不然可能效率会更低。线程池也是不错的选择。如果觉得用系统的不好,你可以先了解java本身的线程机制,然后自己手工写一个效率更高的。
      

  18.   

    对于你这样无限制的开线程,我不太赞同,你的cpu扛不住的,用一个监控线程去管理,控制开启线程的数量。
    对于字符编码问题,你可以通过的到返回html,从头部拿到起字符编码,当然不是所有的都可以拿到。
    想做爬虫,你可以看看httpclient,这个很好用的