轻量级爬虫实例——爬取百度百科1000个页面的数据

轻量级爬虫实例——爬取百度百科1000个页面的数据

爬虫程序baike_spider分为5个模块:
——爬虫总调度程序 (spider_main)
——url管理器 (url_manager)
——网页下载器 (html_downloader)
——网页解析器 ( html_parser)
——将数据处理好的数据写出到 html 的页面 (html_outputer)

爬虫总调度程序(spider_mian):

from baike_spider import url_manager,html_parser,html_downloader,html_outputer  #总调度程序导入其余模块

class SpiderMain(object):          #创建SpiderMain爬虫类
    def __init__(self):            #初始化模块对象
        self.urls = url_manager.UrlManager()     #urlg管理器对象 
        self.downloader = html_downloader.HtmlDownloader()    #网页下载器对象
        self.parser =  html_parser.HtmlParser()    #网页解析对象
        self.outputer = html_outputer.HtmlOutputer()     #网页输出对象
        
    def crawling(self,root_url):      #通过入口页爬取相关词条数据
        count = 1       #爬取页面数量统计量
        self.urls.add_new_url(root_url)             #向待爬取url集合添加入口url
        
        while self,urls.has_new_url():               #循环爬取,条件:待爬取url集合非空
            try:                                     # 可能出现解析出的url无法打开或者内容丢失,进行异常处理
                new_url= self.urls.get_new_url()         #从待爬取的url集合中取出一个url
                print("crawling %d: %s"%(count,new_url)        #打印爬取进度状态信息
                html_cont = self.downloader.download(new_url)    #下载url的html文本
                new_urls,new_data = self.parser.parse(new_url,html_cont)   #解析入口页html文本得出入口页中所有相关url存入new_urls变量
                self.urls.add_new_urls(new_urls)        #new_urls变量中的url加入到待爬取集合中 
                self.outputer.collect_data(new_data)         #收集标题、简介数据存入列表
                
                if count ==1000:   #统计达到 1000退出循环
                    break
                   
                count+=1     #循环一次自加1
            except:
                print("crawling failed")    #爬取失败则打印出错信息crawling failed
                
        self.outputer.output_html()     #将url 标题 简介 输出为html文件
            
if __name = "__mian__":
    root_url = "https://baike.baidu.com/item/Python/407313"     #入口页
    obj_spider = SpiderMain()        #创建爬虫对象 
    obj_spider.crawling(root_url)    #爬取并输出数据

URL管理器模块(url_manager):

class UrlManager(object):       #创建UrlManager类
    def __init__(self):             #初始化待爬取集合和已爬取集合
        self.new_urls = set()       #待爬取集合 
        self.old_urls = set()       #已爬取集合
    def add_new_url(self,url):     #添加新url方法 
        if url is None:            #url为空,返回
            return
        if url not in old_urls and url not in new_urls:    #url都不在待爬取和已爬取集合中,进行添加
            self.new_urls.add(url)       #集合添加为内置add方法
    def add_new_urls(self,urls):          #添加多个url
        if urls is None or len(urls) ==0:    #urls为空或者urls的长度为0
            return
        for url in urls:         #依次添加urls中的url进待爬取集合
            self.add_new_url(url)
    def has_new_url(self):      #待爬取集合非空 返回True
        return len(self.new_urls) != 0 
    def get_new_urls(self):           #取出待爬取集合中的一个url
        new_url = self.new_urls.pop()    #取出
        self.old_urls.add(new_url)       #同时放入已爬取集合
        return new_url          #返回取出的url

网页下载器 (html_downloader)

from urllib2 import request       #导入urllib2包的request模块

class HtmlDownloader(objct):    #创建HtmlDownloader类
    def download(self,url):            #url非空则下载其对应的html文本
        if url is None:
            return None
        request1= request.Request(url)           #初始化request对象 
        request1.add_header("user-agent", "Mozilla/5.0")       #添加请求头,模拟浏览器
        response = request.urlopen(request1)      #打开url对应的html
        if response1.getcode != 200:      #状态为 200,访问成功
            return None
        return respone.read()     #返回html文本

网页解析器 ( html_parser)

from bs4 import BeautifooulSoup         #导入模块
from urllib.parse import urlparse
import re   #urlparse是url解析器 

class HtmlParser(object):          #创建HtmlParser类
    def _get_new_urls(self, page_url, soup):    #解析html文本获取urls的方法
        in_page_urls = set()        
        links = soup.find_all('a', href=re.compile(r"/item/\S+/\d+"))          #找到所有满足的url
  
        for link in links:
            new_url = link['href']
            new_full_url = urljoin(page_url, new_url)      #urljoin可以将基地址与相对地址形成一个绝对地址
             in_page_urls.add(new_full_url)
        return  in_page_urls

    def _get_new_data(self, page_url, soup):     #解析url对应的标题、简介数据
        res_data = {}          #数据字典 
        res_data['url'] = page_url    #键url
        title_node = soup.find('dd', class_="lemmaWgt-lemmaTitle-title").find("h1")   #找出标题
        res_data['title'] = title_node.get_text()       #键title

        summary_node = soup.find('div', class_="lemma-summary")     #找出简介
        res_data['summary'] = summary_node.get_text()        #键summary
        return res_data      #返回url对应的字典 

    def parse(self, page_url, html_cont):       #url为非空或者html为非空时解析
        if page_url is None or html_cont is None:      
            return 
        soup = BeautifulSoup(html_cont, 'html.parse', from_encoding='utf-8')      #解析html文本
        new_urls = self._get_new_urls(page_url, soup)       #得出html中的urls
        new_data = self._get_new_data(page_url, soup)     #得出html中的标题和简介
        return new_urls, new_data       #返回html中的urls和输出数据字典 

网页输出(html_outputer):

class HtmlOutputer(object):      #创建HtmlOutputer类
    def __init__(self):    
        self.datas=[]     #列表
    #收集数据
    def collect_data(self,data):    #数据非空放入列表
        if data is None:
            return
        self.datas.append(data)
        
    def output_html(self):
        fout=open('output.html','w',encoding='utf-8')
        #输出到output.html中,w为写模式,编码为utf-8
        fout.write("<html>")
        fout.write("<body>")
        fout.write("<table>")
        
        #ASCI
        for data in self.datas:     #列表分条写入fout这个html文档
            fout.write("<tr>")
            fout.write("<td>s%</td>" % data['url'])
            fout.write("<td>s%</td>" % data['title'])
            fout.write("<td>s%</td>" % data['summary'])
            fout.write("</tr>")
        
        
        fout.write("</table>")
        fout.write("</body>")
        fout.write("</html>")
        fout.close()      #关闭fout文件

猜你喜欢

转载自blog.csdn.net/qq_42415326/article/details/89378314