简单的python爬虫(爬取百度百科词条)

本文是针对慕课网关于python爬虫课程的总结记录!

1、简介

一个完整的爬虫架构包括:调度程序、url管理器、网页下载器、网页解析器。

调度程序:即爬虫的主函数

url管理器:url管理的功能就是管理未爬取的url和已经爬取的url,常见的实现方式有:内存(使用python的set实现)、关系数据库、缓存数据库(菲关系型数据库,如redis)

网页下载器:将互联网上的url对应的网页下载到本地的工具,以便后续分析处理。常见的网页下载器:urllib2(官方)、request(第三方)

网页解析器:网页内容下载之后需要解析之后才能判断里面是否存在我们需要的内容,那么网页解析器就是完成这个功能的。常见的网页解析器的实现方式有:正则表达式、html.parser(官方)、beautifulSoup(第三方插件,强大),lxml


2、实战代码

本节给出课程中对百度百科中与python词条相关的1000个词条(IDE为eclipse下的PyDev)

2.1 调度程序

#coding:utf-8
'''
Created on 2016年5月15日

@author: Owen
'''
from spider import url_maneger, html_downloader, html_parser, html_outputer


class SpiderMain(object):
    def __init__(self):
        self.urls = url_maneger.UrlManager()
        self.downloader = html_downloader.HtmlDownloader()
        self.parser = html_parser.HtmlParser()
        self.outputer = html_outputer.HtmlOutputer()

    def craw(self, root_url):
        count = 1
        self.urls.addNewUrl(root_url)
        while self.urls.hasNewUrl():
            try:
                new_url = self.urls.getNewUrl()
                print('craw %d:%s'%(count,new_url))
                html_cont = self.downloader.download(new_url)
                new_urls,new_data = self.parser.parse(new_url,html_cont)
                self.urls.addNewUrls(new_urls)
                self.outputer.collectData(new_data)
                
                if count == 1000:
                    break;
                count += 1
            except:
                print("craw failed!")
        self.outputer.outputHtml()

if __name__ == '__main__':
    root_url = "http://baike.baidu.com/view/21087.htm"
    obj_spider = SpiderMain()
    obj_spider.craw(root_url)
2.2 url管理器

#-*- coding: UTF-8 -*-
'''
Created on 2016年5月15日

@author: Owen
'''
        
class UrlManager(object):
    def __init__(self):
        self.newUrls = set()   #未爬取的url集合
        self.oldUrls = set()    #已经爬取的url集合
        
    def hasNewUrl(self):
        return len(self.newUrls)!=0

    def getNewUrl(self):
        new_url = self.newUrls.pop()
        self.oldUrls.add(new_url)
        return new_url
        
    def addNewUrl(self,url):
        if url is None:
            return
        if url not in self.newUrls and url not in self.oldUrls:
            self.newUrls.add(url)
        
    def addNewUrls(self,urls):
        if urls is None or len(urls)==0:
            return
        for url in urls:
            self.addNewUrl(url)


2.3 网页下载器

#-*- coding: UTF-8 -*-
'''
Created on 2016年5月15日

@author: Owen
'''
import urllib2
        
class HtmlDownloader(object):
    
    def download(self,url):
        if url is None:
            return None
        response = urllib2.urlopen(url)
        
        if response.getcode() != 200:   #检测状态码是否为200,200代表成功
            return None
        
        return response.read()

2.4 网页解析器

#-*- coding: UTF-8 -*-
'''
Created on 2015年5月15日

@author: Owen
'''
from bs4 import BeautifulSoup
import re
import urlparse
        
class HtmlParser(object):
  
    def getNewUrls(self, page_url, soup):
        links = soup.find_all('a',href = re.compile(r"/view/\d+\.htm"))
        new_urls = set()
        
        for link in links:
            new_url = link['href']
            new_full_url = urlparse.urljoin(page_url,new_url)
            new_urls.add(new_full_url)
        return new_urls
    
    
    def getNewData(self, page_url, soup):
        res_data = {}
        #url
        res_data['url'] = page_url
        
        #<dl class="lemmaWgt-lemmaTitle lemmaWgt-lemmaTitle-">
        #<h1>Python</h1><dd class="lemmaWgt-lemmaTitle-title">
        title_node = soup.find('dd',class_="lemmaWgt-lemmaTitle-title").find("h1")
        res_data['title'] = title_node.get_text()
        
        #<div class="lemma-summary" label-module="lemmaSummary">
        summary_node = soup.find('div',class_ = "lemma-summary")
        res_data['summary'] = summary_node.get_text()
        
        return res_data
    
    
    def parse(self,page_url,html_cont):
        if page_url is None or html_cont is None:
            return
        
        soup = BeautifulSoup(html_cont,'html.parser',from_encoding='utf-8')
        
        new_urls = self.getNewUrls(page_url,soup)
        new_data = self.getNewData(page_url,soup)
        return new_urls,new_data

2.5 文件保存

#-*- coding: UTF-8 -*-
'''
Created on 2016年5月15日

@author: Owen
'''
#将爬取之后的网页保存到本地文件中,保存为网页格式

class HtmlOutputer(object):
    
    def __init__(self):
        self.datas=[]
        
    
    def collectData(self,data):
        if data is None:
            return
        self.datas.append(data)

    
    def outputHtml(self):
        fout = open('output.html','w')
        
        fout.write("<html>")
        fout.write("<body>")
        fout.write('<head><meta charset="utf-8"></head>')   #告诉浏览器使用何种编码
        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'].encode('utf-8'))
            fout.write("<td>%s</td>"%data['summary'].encode('utf-8'))
            fout.write("</tr>")
            
        fout.write("</table>")
        fout.write("</body>")
        fout.write("</html>")

2.6 运行结果





猜你喜欢

转载自blog.csdn.net/owen7500/article/details/51417418
今日推荐