1. 程式人生 > >爬取N個網頁,並將其記錄

爬取N個網頁,並將其記錄

color 完整 encode down utf 模塊 round 初始 函數

挖的坑,終於能填上了,先共享出來,大家有個對比參考。也幫忙找找錯誤。我也正在看,看看原來是哪裏出了問題。

下面這段代碼已經實現了網頁的爬取:

其效果為:

技術分享

下面給出詳細說明:

技術分享

上圖中出現的 __init__.py 文件,是一個空的,但是必須建立(我也沒想明白為啥)。

程序結束後,打開output.html 就可以了。

1.這是網頁管理模塊 url_manager.py (點擊+號,看代碼)

技術分享
class UrlManager(object):
    
    def __init__(self):
        self.new_urls=set()
        self.old_urls
=set() #向管理器中添加一個新的url def add_new_url(self,url): if url is None: return if url not in self.new_urls and url not in self.old_urls: self.new_urls.add(url) #向管理器中添加多個新的url def add_new_urls(self,urls): if urls is None or
len(urls)==0: return for url in urls: self.add_new_url(url) #判斷管理器中是否還有新的待爬取的url def has_new_url(self): return len(self.new_urls)!=0 #從管理器中獲取一個新的待爬取的url def get_new_url(self): new_url=self.new_urls.pop()#獲取並移除 self.old_urls.add(new_url)#
添加至舊的集合 return new_url
View Code

2.這是下載網頁模塊 html_downloader.py

技術分享
import urllib.request
class HtmlDownloader(object):
    
    #下載一個url裏的數據
    def download(self,url):
        if url is None:
            return None
        response=urllib.request.urlopen(url)#註意py2和py3不同
        if response.getcode()!=200:#狀態碼200表示獲取成功
            return None
        return response.read()#返回下載好的內容
View Code

3.這是網頁解析模塊 html_parser.py

技術分享
from bs4 import BeautifulSoup
import re
import urllib.parse
#py3中urlparse在urllib中
class HtmlParser(object):
    
    #返回新的url集合
    def _get_new_urls(self,page_url,soup):
        new_urls=set()
        #獲取所有的鏈接,用正則匹配
        links=soup.find_all(a,href=re.compile(r"/item/"))
        for link in links:
            new_url=link[href]#獲取它的鏈接(不完全)
            #將不完整的new_url按照page_url的格式拼成完整的
            new_full_url=urllib.parse.urljoin(page_url,new_url)
            new_urls.add(new_full_url)
        return new_urls
    
    #返回對soup的解析結果
    def _get_new_data(self,page_url,soup):
        res_data={}
        #url
        res_data[url]=page_url
        
        #<dd class="lemmaWgt-lemmaTitle-title"><h1>Python</h1>
        #獲取詞條名(用了兩次find)
        title_node=soup.find(dd,class_="lemmaWgt-lemmaTitle-title").find("h1")
        #註意這裏先split再做join,將\\變成了\
        res_data[title]=\\.join(title_node.get_text().split(\\\\))#加入字典中
        
        #<div class="lemma-summary">
        #獲取摘要文字
        summary_node=soup.find(div,class_="lemma-summary")
        #註意這裏先split再做join,將\\變成了\
        res_data[summary]=\\.join(summary_node.get_text().split(\\\\))#加入字典中
        
        return res_data
    
    #解析一個下載好的頁面的數據,並返回新的url列表和解析結果
    def parse(self,page_url,html_cont):
        if page_url is None or html_cont is None:
            return
        #創建一個bs對象(將網頁字符串html_cont加載成一棵DOM樹)
        soup=BeautifulSoup(html_cont,html.parser)
        new_urls=self._get_new_urls(page_url,soup)
        new_data=self._get_new_data(page_url,soup)
        return new_urls,new_data
View Code

4.下面是網頁輸出模塊 html_outputer.py

技術分享
class HtmlOutputer(object):
    
    def __init__(self):
        self.datas=[]
        
    #收集解析好的數據
    def collect_data(self,data):
        if data is None:
            return
        self.datas.append(data)
    
    #輸出所有收集好的數據
    def output_html(self):
        with open(output.html,w) as fout:
            fout.write("<html>")
            ‘‘‘fout.write("<head>")
            fout.write("<meta  charset=\"utf-8\">")
            fout.write("</head>")‘‘‘
            fout.write("<body>")
            fout.write("<table>")
            for data in self.datas:
                fout.write("<tr>")
                fout.write("<td>%s</td>"%data[url])
                fout.write("<td>%s</td>"%data[title])
                fout.write("<td>%s</td>"%data[summary].encode(utf-8))
                fout.write("</tr>")
            fout.write("</table>")
            fout.write("</body>")
            fout.write("</html>")
            fout.close()
View Code

5.主函數,運行這個就可以了

技術分享
import url_manager,html_downloader,html_parser,html_outputer

class SpiderMain(object):
    
    def __init__(self):#在構造器中初始化所需要的對象
        self.urls=url_manager.UrlManager()#url管理器
        self.downloader=html_downloader.HtmlDownloader()#下載器
        self.parser=html_parser.HtmlParser()#解析器
        self.outputer=html_outputer.HtmlOutputer()#價值數據的輸出
        
    def craw(self,root_url):
        count=1#記錄當前爬取的是第幾個url
        self.urls.add_new_url(root_url)#先將入口url給url管理器
        #啟動爬蟲的循環
        while self.urls.has_new_url():#如果管理器中還有url
            try:
                new_url=self.urls.get_new_url()#就從中獲取一個url
                print (craw %d : %s%(count,new_url))#打印正在爬的url
                html_cont=self.downloader.download(new_url)#然後用下載器下載它
                #調用解析器去解析這個頁面的數據
                new_urls,new_data=self.parser.parse(new_url,html_cont)
                self.urls.add_new_urls(new_urls)#新得到的url補充至url管理器
                self.outputer.collect_data(new_data)#收集數據
                if count==30:#如果已經爬了30個直接退出
                    break
                count+=1
            except:
                print (craw failed)#標記這個url爬取失敗
        self.outputer.output_html()#循環結束後輸出收集好的數據
            
            

if __name__=="__main__":
    root_url="http://baike.baidu.com/item/Python"#入口url
    obj_spider=SpiderMain()
    obj_spider.craw(root_url)
View Code

以上內容,來自:http://blog.csdn.net/shu15121856/article/details/72903146

爬取N個網頁,並將其記錄