zoukankan      html  css  js  c++  java
  • 网络爬虫初步:从訪问网页到数据解析

    前言:

      网络爬虫这个东西看上去还是非常奇妙的。

    只是,假设你细想。或是有所研究就知道,事实上爬虫并不那么高深。

    高深的是在我们的数据量非常大的时候,就是当我们网络“图”的回环越来越多的时候。应该怎么去解决它。

      本篇文章在这里仅仅是起一个抛砖引玉的作用。本文主要是解说了怎样使用Java/Python訪问网页并获得网页代码、Python模仿浏览器进行訪问网页和使用Python进行数据解析。

    希望我们以本文開始。一步一步解开网络蜘蛛神奇的一面。


    參考:

    1.《自己动手写网络爬虫》

    2.用python 写爬虫,去爬csdn的内容,完美解决 403 Forbidden


    执行效果图:

      


      内容有点多。我仅仅选取了一部分进行展示。


    笔者环境:

      系统:     Windows 7

                CentOS 6.5

      执行环境:  JDK 1.7

                Python 2.6.6

      IDE:      Eclipse Release 4.2.0

                PyCharm 4.5.1

      数据库:    MySQL Ver 14.14 Distrib 5.1.73


    开发过程:

    1.使用Java抓取页面

      对于页面抓取我们採用Java来实现,当然你能够使用其它的语言来开发。只是

      以下以“博客园”的首页为例,展示一下使用Java进行网页页面抓取的过程:

    public class RetrivePageSimple {
    	
    	private static HttpClient httpClient = new HttpClient();
    	
    	// 设置代理server
    	static {
    		httpClient.getHostConfiguration().setProxy("58.220.2.132", 80);
    	}
    
    	public static boolean downloadPage(String path) throws HttpException,
    			IOException {
    		PostMethod postMethod = new PostMethod(path);
    		
    		// 运行,返回状态码
    		int statusCode = httpClient.executeMethod(postMethod);
    		System.out.println(statusCode);
    		
    		// 针对状态码进行处理 (简单起见。仅仅处理返回值为200的状态码)
    		if (statusCode == HttpStatus.SC_OK) {
    			
    			String a = postMethod.getResponseBodyAsString();
    			System.out.println(a);
    			
    			return true;
    		}
    		
    		return false;
    	}
    
    	public static void main(String[] args) {
    		try {
    			RetrivePageSimple.downloadPage("http://www.cnblogs.com/");
    		} catch (HttpException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
     
      结果信息在这里就不再展示,太多了。。。

    - -!


    2.使用Python抓取页面

      可能你会问我,为什么上面写了使用Java版的页面抓取,这里又要写一个Python?这是有必要的。由于笔者在开发这个demo之前没有考虑一个问题。我们使用Java抓取了一个网页给Python的时候,这个网页字符串过长,无法作为參数传递。

    可能你会认为保存文件是一个不错的选择,那html文件太多又要怎么办呢?是的,这里我们不得不舍弃这样的让人心累的做法。

      考虑到是由于參数长度的限制,这里我们在Java端仅仅给出页面地址,抓取网页使用Python来进行。

      依照最简单的方式,通常我们会像这样来使用Python网页:

    import urllib2
    result = urllib2.urlopen('http://blog.csdn.net/mobile/index.html')
    html = result.read()
    
    print html

      但是,笔者代码中使用的是CSDN的博客频道的url。CSDN对来自爬虫的訪问进行一层过滤,例如以下我们会得到例如以下错误信息:

      

      403,我被拒绝了。


    3.使用模仿浏览器登录站点

      前面说到我们去訪问带有保护措施的网页时,会被拒绝。只是我们能够尝试使用自己的浏览器来訪问它,是能够訪问的。

      也就是说假设我们能够在Python中去模仿自己是浏览器就能够对这个网页进行訪问了。以下是Python模仿浏览器的代码:

    import random
    import socket
    import urllib2
    import cookielib
    
    ERROR = {
            '0':'Can not open the url,checck you net',
            '1':'Creat download dir error',
            '2':'The image links is empty',
            '3':'Download faild',
            '4':'Build soup error,the html is empty',
            '5':'Can not save the image to your disk',
        }
    
    class BrowserBase(object):
    
        def __init__(self):
            socket.setdefaulttimeout(20)
            self._content = None
    
        def speak(self, name, content):
            print '[%s]%s' % (name, content)
    
        def open_url(self, url):
            """
            打开网页
            """
            cookie_support= urllib2.HTTPCookieProcessor(cookielib.CookieJar())
            self.opener = urllib2.build_opener(cookie_support,urllib2.HTTPHandler)
            urllib2.install_opener(self.opener)
            user_agents = [
                        'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11',
                        'Opera/9.25 (Windows NT 5.1; U; en)',
                        'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
                        'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)',
                        'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12',
                        'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9',
                        "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.7 (KHTML, like Gecko) Ubuntu/11.04 Chromium/16.0.912.77 Chrome/16.0.912.77 Safari/535.7",
                        "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0 ",
                        ]
           
            agent = random.choice(user_agents)
            self.opener.addheaders = [("User-agent", agent), ("Accept", "*/*"), ('Referer', 'http://www.google.com')]
    
            try:
                res = self.opener.open(url)
                self._content = res.read()
                # print self._content
            except Exception, e:
                self.speak(str(e)+url)
                raise Exception
            else:
                return res
    
        def get_html_content(self):
            return self._content
    
    def get_html_response(html):
        spider = BrowserBase()
        spider.open_url(html)
        return spider.get_html_content()

      上面的代码是能够正常得到返回值的。

    例如以下就来看看对返回的结果的解析过程吧。


    4.数据解析

      使用Python来进行Html的解析工作,是异常的简单:

    import HTMLParser
    
    class ListWebParser(HTMLParser.HTMLParser):
        def __init__(self):
            HTMLParser.HTMLParser.__init__(self)
            self.tagDIVFlag = False
            self.tagDIVAFlag = False
            self.tagH1Flag = False
            self.tagSecondHrefFlag = False
    
            self._name = None
            self._address = None
    
        def handle_starttag(self, tag, attrs):
            if tag == 'div':
                for name, value in attrs:
                    if name == 'class' and value == 'blog_list':
                        self.tagDIVFlag = True
    
            if tag == 'h1':
                if self.tagDIVFlag:
                    self.tagH1Flag = True
                    # print 'h1->', self.tagH1Flag
    
            if tag == 'a':
                #if self.tagDIVAFlag:
                    #print 'h1: ', self.tagH1Flag
                if self.tagH1Flag:
                    for name, value in attrs:
                        if name == 'target' and value == '_blank':
                            self.tagDIVAFlag = True
    
                        if name == 'href':
                            if self.tagSecondHrefFlag:
                                print '网址:', value
                                self._address = value
                            self.tagSecondHrefFlag = True
    
                        # if name == 'href' and self.tagDIVAFlag:
                            # print '网址:', value
                            # self._address = value
    
        def handle_endtag(self, tag):
            if tag == 'div':
                self.tagDIVFlag = False
    
            if tag == 'h1':
                self.tagH1Flag = False
                # print 'false h1.'
    
            if tag == 'a':
                self.tagDIVAFlag = False
    
        def handle_data(self, data):
            if self.tagDIVAFlag:
                print u"名称:", data.decode("utf-8")

      假设你说你在网上查找到的Html文件没有这个麻烦。这个我是承认的,由于正常情况下,我们解析一些简单数据的确非常easy。上面代码中的复杂逻辑是在处理筛选。

      说到筛选,这里我用到一个小技巧(当然,当用的人多了,这就不再仅仅是技巧。

    只是这样的方法能够在以后的编码过程中有所借鉴)。我们通过一些tag的特殊属性(如:id, class等)来锁定块。当我们開始块的时候。我们对应的标志位会被打成True。当我们退出块的时候,我们对应标志位会被打成False。可能你认为这太麻烦。事实上。你细致想想就会知道。这是有道理的。


    注意事项:

    1.在使用Java进行页面抓取的时候,我们用到了代理server。这个代理server的host和port是能够直接在网上查到免费的。


    2.你须要准备下面jar包。并导入到你的Eclipseproject中:



    3.改动MySQL的默认编码为UTF-8

      这里由于会有一些中文信息。所以我们须要对MySQL进行编码格式的转换。

      假设你是在Linux下编码。那么你能够參考:http://blog.csdn.net/lemon_tree12138/article/details/46375637

  • 相关阅读:
    【校招面试 之 C/C++】第23题 C++ STL(五)之Set
    Cannot create an instance of OLE DB provider “OraOLEDB.Oracle” for linked server "xxxxxxx".
    Redhat Linux安装JDK 1.7
    ORA-10635: Invalid segment or tablespace type
    Symantec Backup Exec 2012 Agent for Linux 卸载
    Symantec Backup Exec 2012 Agent For Linux安装
    You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1
    YourSQLDba介绍
    PL/SQL重新编译包无反应
    MS SQL 监控数据/日志文件增长
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6979107.html
Copyright © 2011-2022 走看看