python爬虫实战:抓取百度百科1000个分级基金的页面信息

Python kingmo888 2465℃ 0评论

在学习计划已经学习了爬虫主要的几个组成本分,接下来就要开始实战演练了。

首先要制定我们的抓取目标:

  • – 百科标题
  • – 简介
  • – 页面内的url连接

根据抓去目标分析下百度百科的页面信息。以百科中{% link 分级基金 http://baike.baidu.com/view/2857537.htm %}页面为入口页面,

 


其标题位置如下:


<dd class="lemmaWgt-lemmaTitle-title">
<h1>分级基金</h1>
<a href=xxxxxx  </a>
</dd>
 

其简介位置如下:


<div class="lemma-summary" label-module="para">简介内容</div>


页面内的url连接格式如下:

<a target="_blank" href="/view/2819716.htm">分级指数基金</a>


URL的构造很简单,不过有一点需要注意,访问url时需要补全其base路径。
同时,正则中要指明htm为结尾,不然可能出现意料不到的url地址。


现在,我们要开始构建爬虫的主要部件了,

  • – __init__.py    包默认文件
  • – spider_main.py         入口主函数
# encoding:utf-8
import url_manager, html_downloader, outputer, html_parser
import time

class SpiderMain(object):
    def __init__(self):
        self.urls = url_manager.UrlManager()
        self.downloader = html_downloader.HtmlDownloader()
        self.parser = html_parser.HtmlParser()
        self.outputer = outputer.HtmlOutputer()
        
    
    def craw(self, root_url):
        print 123
        self.urls.add_new_url(root_url)
        count = 1
        while self.urls.has_new_url():
            new_url = self.urls.get_new_url()
            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.add_new_urls(new_urls)
            self.outputer.collect_data(new_data)
            time.sleep(0.1)
            if count == 100:
                break
            count += 1

        self.outputer.output_html()
            
    
    

if __name__ == '__main__':
    root_url = 'http://baike.baidu.com/view/2857537.htm'
    obj_spider = SpiderMain()
    craw = obj_spider.craw(root_url)

 

  • – html_parser.py         网页解析器,用于提取网页内容、提取页内连接
# encoding:utf-8
from bs4 import BeautifulSoup
import re
import urlparse
class HtmlParser(object):
    
    
    def _get_new_urls(self, page_url, soup):
        new_urls = set()
        # $在正则中指明必须以前面什么结尾。
        links = soup.find_all('a',href=re.compile(r'/view/\d+\.htm$'))
        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 _get_new_data(self, page_url, soup):
        res_data = {}
        
        # url
        res_data['url'] = page_url
        
        #<dd class="lemmaWgt-lemmaTitle-title"> <h1>title</h1>
        title_note = soup.find('dd', class_='lemmaWgt-lemmaTitle-title').find('h1')
        res_data['title'] = title_note.get_text()
        
        #<div class="lemma-summary" label-module="lemmaSummary">
        summary_note = soup.find('div', class_='lemma-summary')
        if summary_note is None:
            # <div class="lemmaWgt-subLemmaListTitle">
            summary_note = soup.find('div', class_='lemmaWgt-subLemmaListTitle')
        res_data['summary'] = summary_note.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._get_new_urls(page_url, soup)
        new_data = self._get_new_data(page_url, soup)
        return new_urls, new_data
    
    

 

  • – outputer.py            数据取完后的处理模块,比如保存、入库等。  
# encoding:utf-8
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):
        fout = open('output.html', 'w')
        
        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'].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>')
        fout.close()

 

  • – url_manager.py         url管理器,用于保证url不重复访问、验证是否还有未访问连接、获取新的连接等。
# encoding:utf-8
class UrlManager(object):
    def __init__(self):
        self.newurls = set()
        self.oldurls = set()
    
    def add_new_url(self, url):
        if url is None:
            return
        if url not in self.newurls or url not in self.oldurls:
            self.newurls.add(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)
    
    def has_new_url(self):
        return len(self.newurls) != 0

    
    def get_new_url(self):
        newurl = self.newurls.pop()
        self.oldurls.add(newurl)
        return newurl

 

  • – html_downloader.py       网页下载器,下载网页内容。
# encoding:utf-8
import urllib2
class HtmlDownloader(object):
    
    
    def download(self, url):
        if url is None:
            return None
        request = urllib2.Request(url)
        request.add_header('user-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) Chrome/48.0.2564.116')
        response = urllib2.urlopen(request)
        
        if response.getcode() != 200:
            return None
        
        return response.read()


– output.html              输出模块自动生成。

爬虫生成的结果

该架构稍加改动即可实现比如新浪财经新闻的爬取,构造一个舆情监控系统,然后配合中文分词等工具打造热点追踪神马的。

当然啦,这个架构只是最简单的爬虫架构,单线程、简单的get访问等。真正的爬虫还可能涉及到登录后访问、用以提高效率的多线程、队列等等。

另外,有些网站的内容是基于ajax的,涉及到的东西就更多了,博主也不会。慢慢来吧。

转载请注明:Python量化投资 » python爬虫实战:抓取百度百科1000个分级基金的页面信息

喜欢 (0)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址