Python爬虫--抓取糗事百科段子

今天使用python爬虫实现了自动抓取糗事百科的段子,因为糗事百科不需要登录,抓取比较简单。程序每按一次回车输出一条段子,代码参考了 http://cuiqingcai.com/990.html 但该博主的代码似乎有些问题,我自己做了修改,运行成功,下面是代码内容:

# -*- coding:utf-8 -*-
__author__ = 'Jz'
import urllib2
import re

#糗事百科爬虫类
class QSBK:
    #初始化
    def __init__(self):
        self.pageIndex = 1
        self.user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64)'
        self.headers = {'User-Agent': self.user_agent}
        #joke的每一个元素是每一页的段子
        self.joke = []
        #判断是否继续运行
        self.enable = False
    
    def getPage(self, pageIndex):
        try:
            URL = 'http://www.qiushibaike.com/hot/page/' + str(pageIndex)
            request = urllib2.Request(url = URL, headers = self.headers)
            response = urllib2.urlopen(request)
            pageContent = response.read().decode('utf-8')
            return pageContent
        except urllib2.URLError, e:
            if hasattr(e, 'reason'):
                print '段子抓取失败,失败原因:', e.reason
                return None
    
    def getJokeList(self, pageIndex):
        pageContent = self.getPage(pageIndex)
        if not pageContent:
            print '段子获取失败...'
            return None
        #第三个组中的内容用于判断段子是否附带图片
        pattern = re.compile(r'<div.*?class="author">.*?<a.*?>.*?<img.*?/>\n(.*?)\n</a>.*?</div>.*?<div class="content">\n\n(.*?)\n<!--.*?-->.*?</div>' +
                         r'(.*?)class="stats">.*?<span.*?class="stats-vote"><i.*?class="number">(.*?)</i>'
                         , re.S)
        jokes = re.findall(pattern, pageContent)
        pageJokes = []
        #过滤带有图片的段子
        for joke in jokes:
            hasImg = re.search('img', joke[2])
            #joke[0]为发布人,joke[1]为段子内容,joke[3]为点赞数量
            if not hasImg:
                pageJokes.append([joke[0].strip(), joke[1].strip(), joke[3].strip()])
        return pageJokes
    
    def loadPage(self):
        if self.enable == True:
            #若当前已看的页数少于两页,则加载新的一页
            if len(self.joke) < 2:
                pageJokes = self.getJokeList(self.pageIndex)
                if pageJokes:
                    self.joke.append(pageJokes)
                    self.pageIndex += 1
    
    #每输入一次回车,打印一条段子
    def getOneJoke(self, pageJokes, page):
        jokes = pageJokes
        for joke in jokes:
            userInput = raw_input('请输入回车键或Q/q: ')
            self.loadPage()
            if userInput == 'Q' or userInput == 'q':
                self.enable = False
                print '退出爬虫...'
                return
            print u'段子内容:%s\n第%d页\t发布人:%s\t赞:%s' % (joke[1], page, joke[0], joke[2])
        
    def start(self):
        print '正在从糗事百科抓取段子,按回车键查看新段子,按Q/q退出...'
        self.enable = True
        self.loadPage()
        page = 0
        while self.enable:
            if len(self.joke) > 0:
                pageJokes = self.joke[0]
                page += 1
                #删除已经读取过的段子页
                del self.joke[0]
                self.getOneJoke(pageJokes, page)

spider = QSBK()
spider.start()

注释已经附上,其中有几点需要注意的地方:

1.需要加上header验证进行伪装,否则无法抓取网页内容

2.正则表达式的书写,需要将内容提取出来以验证是否有附带图片

3.getOneJoke函数中格式化输出段子时,需要在字符串前加上u,否则会报如下错误:

Traceback (most recent call last):
  File "D:\coding_file\python_file\TestPython\src\Test\QSBK.py", line 84, in <module>
    spider.start()
  File "D:\coding_file\python_file\TestPython\src\Test\QSBK.py", line 81, in start
    self.getOneJoke(pageJokes, page)
  File "D:\coding_file\python_file\TestPython\src\Test\QSBK.py", line 68, in getOneJoke
    print '段子内容:%s\n第%d页\t发布人:%s\t赞:%s' % (joke[1], page, joke[0], joke[2])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 3: ordinal not in range(128)

这是因为Python默认编码方式为Unicode,所以joke[0]等也是Unicode编码,为了格式化输出,前面的字符串也需要转换成Unicode编码

转载于:https://my.oschina.net/fairy1674/blog/736315

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值