用python編寫網頁爬蟲

來源:互聯網
上載者:User

        一、前期準備

        為了完成一個網頁爬蟲的小程式,需要有以下準備:

        1 瞭解基本的http協議

        2 urllib2庫介面熟悉

        3 熟悉pythonRegex

        

        二、程式編寫思路

        這裡只是實現一個基本的網頁爬蟲程式,它的基本思路如下:

        1 尋找到需要抓取的網頁,查看其原始碼,分析需要擷取網頁頁面的html規律

        2 利用urllib2庫來讀取所需要的網頁

        3 利用Regex正確提取出所需要的網頁資訊

        4 對擷取的網頁資料資訊進行有效性校正工作,即資訊的甄別

        5 對有效資料資訊進行儲存,如存放於檔案,或資料庫db中

        三、抓取網頁Proxy 伺服器爬蟲的執行個體

        找到一個Proxy 伺服器的網站,如http://www.cnproxy.com/,我們需要將http://www.cnproxy.com/proxy1.html下的IP,連接埠,type和area欄位提取出來。主要利用Regex和urllib2庫,代碼如下:

        

proxylist1=Queue.Queue()#用於存放從頁面中抓取的所有伺服器代理IP地址和連接埠號碼portdicts = {'z':"3", 'm':"4", 'a':"2", 'l':"9", 'f':"0", 'b':"5", 'i':"7", 'w':"6", 'x':"8", 'c':"1", 'r':"8", 'd':"0"}def get_proxy_from_cnproxy():    global proxylist1    p = re.compile(r'''<tr><td>(.+?)<SCRIPT type=text/javascript>document.write\(":"\+(.+?)\)</SCRIPT></td><td>(.+?)</td><td>.+?</td><td>(.+?)</td></tr>''')            for i in range(1,11):        target = r"http://www.cnproxy.com/proxy%d.html" %i        print target        req = urllib2.urlopen(target)        result =  req.read()        matchs = p.findall(result)        #print matchs                for row in matchs:            ip = row[0]            port = row[1]            if port is None:                continue            tmp = port.split('+')                        #發現在html中的連接埠找不到一些鍵所對應的值,過濾掉這些IP            flag = 0            for x in tmp:                if x  not in portdicts:                    flag = 1                    break            if flag == 1:                continue                        port = map(lambda x: portdicts[x], port.split('+'))            port = ''.join(port)            agent = row[2]            addr = row[3].decode("cp936").encode("utf-8")                    l = [ip, port, agent, addr]            print l            proxylist1.put(l)            print "page 1-10 size:%s nums proxy info" %proxylist1.qsize()  

        

        上述程式碼完成將所需要的網頁欄位提取出來存放到隊列proxylist1中。緊接著需要對隊列proxylist1中的每個欄位進行校正,判斷裡面資料的有效性,然後將檢測到的資料存放於另一隊列ProxyCheckedList中,然後對有效資料資訊進行一個排序,最後將其儲存於檔案中。代碼如下:

ProxyCheckedList = Queue.Queue()#用於存放經校正後得到的有效代理IP地址和連接埠號碼資訊        class ProxyCheck(threading.Thread):    def __init__(self, fname):        threading.Thread.__init__(self)        self.timeout = 5        #self.test_url = "http://www.baidu.com/"        #self.test_str = "030173"        #self.test_url = "http://www.so.com/"        #self.test_str = '08010314'        self.test_url="http://www.renren.com"        self.test_str="110000000009"        self.fname = fname        self.checkedProxyList = []            def checkProxy(self):        threadpool = []        for i in range(10):#開闢10個線程放到線程池中            threadpool.append(ck_process(self.test_url, self.test_str,self.timeout,i))                #啟動10個線程同時處理校正工作            map(lambda x: x.start(), threadpool)                #等待線程退出        map(lambda x: x.join(), threadpool)                while ProxyCheckedList.empty() == False:            try:                content = ProxyCheckedList.get_nowait()            except Exception,e:                print e            else:                self.checkedProxyList.append(content)        print "the checked proxylist contains: %s nums records"%len(self.checkedProxyList)        for info in self.checkedProxyList:            print info            def sort(self):        sorted(self.checkedProxyList, cmp=lambda x,y:cmp(x[4], y[4]))#對回應時間的代理ip列表進行排序        def save(self):        f = open(self.fname, 'w+')        for proxy in self.checkedProxyList:            f.write("%s:%s\t%s\t%s\t%s\n"%(proxy[0], proxy[1], proxy[2], proxy[3], proxy[4]))        f.close()        def run(self):        self.checkProxy()        self.sort()        self.save()        print 'Done'

        這個類主要繼承於線程類threading,它的程式流程主要看run(),它的過程就是上面分析的思路。下面對checkProxy()這個過程進行簡要說明,它建立了10個線程,利用map函數讓這十個線程同時啟動,最後是等待線程的退出。然後對隊列中ProxyCheckedList的資料再次加工就完成了。而這10個線程他們乾的事情是相同的,他們依次從一個隊列ProxyCheckedList中讀出10條http代理資料(IP,連接埠等),然後迭代對這10條資料進行有效性判斷,有效性判斷的思路如下:

        用urllib2.HTTPCookieProcessor()建立一個cookie,

        利用每個資料的IP和連接埠構定一個代理控制代碼對象proxy_handler = urllib2.ProxyHandler({"http":r'http://%s:%s'%(proxy[0],proxy[1])})

        將代理控制代碼與cookie綁定opener = urllib2.build_opener(cookies, proxy_handler)

        請求對象的安裝urllib2.install_opener(opener)

        最後是利用這個代理IP訪問某個網站,如果在某一規定的時間內有資料返回,則說明有效,將其放至隊列ProxyCheckedList中,否則迭代下一個。下面是代碼:

class ck_process(threading.Thread):    '''線程類:用於多執行緒校正代理IP的有效性'''        def __init__(self,test_url, test_str, timeout,count):        threading.Thread.__init__(self)        self.proxy_contain = []        self.test_url = test_url        self.test_str = test_str        self.checkedProxyList = []        self.timeout = timeout        self.count = count    def run(self):                cookies = urllib2.HTTPCookieProcessor()#構造一個cookie對象        #print "I'm thread process No. %s" %self.count        while proxylist1.empty() == False:            if lock_que.acquire():#成功擷取鎖                if proxylist1.qsize() >= 10:                    number = 10                else:                    number = proxylist1.qsize()                                    for i in range(number): #從原始的列表隊列中擷取出10條代理IP資訊                    proxy = proxylist1.get_nowait()                    self.proxy_contain.append(proxy)                    #print "%s thread process:%s"%(self.count,self.proxy_contain)                    #print                lock_que.release()                                        #每個線程每次逐一處理10條                for proxy in self.proxy_contain:                                proxy_handler = urllib2.ProxyHandler({"http":r'http://%s:%s'%(proxy[0],proxy[1])})#構造一個代理控制代碼對象                opener = urllib2.build_opener(cookies, proxy_handler)#將代理控制代碼與cookie綁定                            #類比一個瀏覽器,加入http的user-agent頭欄位,參數放入列表的元組                opener.addheaders=[('user-agent','Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31')]                urllib2.install_opener(opener)#請求註冊                t1 = time.time() #get current time                try:#有時某些代理無效打不開網站                    req = urllib2.urlopen(self.test_url, timeout = self.timeout)                    result = req.read()                    timeused = time.time() - t1                    pos = result.find(self.test_str)                            if pos > 1:                        self.checkedProxyList.append((proxy[0],proxy[1], proxy[2], proxy[3], timeused))                    else:                        continue                                    except Exception, e:                    #print e.message                    continue                if len(self.checkedProxyList) != 0:            if lock_que_cked.acquire():                for proxy in self.checkedProxyList:                    ProxyCheckedList.put(proxy)                lock_que_cked.release()                 print "%s thread process:out: %s nums"%(self.count, len(self.checkedProxyList))

        (完)
  

   

        

     

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.