Python爬虫实践笔记(二)

无登录百度贴吧的帖子

基本步骤:
①分析url ②获取页面 ③提取信息 ④文本处理 ⑤写入文件

备注:
基本框架跟笔记(一)很相似,只是多了很多细节需要处理,所以这里着重描述细节的处理。

第一步:分析url

(1)像段子、贴吧这种会存在多种页数的网站,各页的url的差别在于url参数部分的值,所以爬取其它页面时需要先去页面看看控制不同页面的url的参数。所以第一步需要看看所寻找的信息的url及其特征。
(2)从url可以知道百度贴吧通过seeLZ参数控制是否只显示楼主的帖子,和通过pn参数控制当前帖子的页面。同时这意味着贴吧是通过GET方式发送请求的。

第二步:获取页面

(1)在这里百度贴吧不需要我们再添加headers信息,同时,从上一步我们知道贴吧通过GET方法发送请求,因此我们只需要使用seeLZ以及pn参数来构建url,然后使用Request方法生成请求,最后使用urlopen方式发送请求获取包含页面源码的响应对象。
(2)这一步我们使用响应对象的read()方法获取页面源码然后编码后返回。

第三步:提取信息

(1)同样地,我们需要查看源码的布局,找出我们想要提取的信息所在的地方,然后使用正则表达式模块提取我们想要的信息。
(2)由于贴吧中帖子内容包含了很多的图片,超链接,空行以及其他无关紧要的字符,因此下一步我们需要对这些字符进行处理,返回干净的文本信息。

第四步:文本提取

(1)由于获取的信息包含了图片、超链接等无关信息,因此需要去除这些信息。为了代码可重用,创建一个工具类来将字符经过一系列处理后返回。
(2)工具类必须能去除图片、超链接、多余的空行和空格、多余的标签,有需要可以同时加入空行调整信息的布局。

第五步:写入文件

(1)为了能够把有用的信息存储起来,这里我们把所有信息写入文本文件。所以需要了解python的文件操作,如打开文件,设置读写文件权限,写入文件,关闭文件等。

最后:构建程序逻辑,实现程序

有些细节地方需要注意:
①中文字符的编码问题,显示到控制台时需要先解码成utf-8,然后编码成gbk,最后输出。
②正则表达式要写对。
③文件操作。

我的程序如下:

# _*_ coding: utf-8 _*_
import urllib
import urllib2
import re

class Tool:
    '文本处理工具类'
    removeImg = re.compile('<img.*?>| {7}|', re.S)
    removeAddr = re.compile('<a.*?>|</a>', re.S)
    replaceLine = re.compile('<tr>|<div>|</div>|</p>')
    replaceTD = re.compile('<td>')
    replacePara = re.compile('<p.*?>', re.S)
    replaceBR = re.compile('<br><br>|<br>')
    removeExtraTag = re.compile('<.*?>', re.S)

    def replace(self, x):
        x = re.sub(self.removeImg, "", x)
        x = re.sub(self.removeAddr, "", x)
        x = re.sub(self.replaceLine, "\n", x)
        x = re.sub(self.replaceTD, "\t", x)
        x = re.sub(self.replacePara, "\n    ", x)
        x = re.sub(self.replaceBR, "\n", x)
        x = re.sub(self.removeExtraTag, "", x)
        return x.strip()

class BDTB:
    '百度贴吧爬虫'
    def __init__(self, baseUrl, seeLZ, floorTag):
        self.baseURL = baseUrl
        self.seeLZ = '?see_lz='+str(seeLZ)
        self.tool = Tool()
        self.file = None
        self.floor = 1
        self.defaultTitle = u'百度贴吧'
        self.floorTag = floorTag

    def getPage(self, pageNum):
        try:
            url = self.baseURL + self.seeLZ + '&pn=' + str(pageNum)
            req = urllib2.Request(url)
            res = urllib2.urlopen(req)
            # print res.read()
            return res.read().decode('utf-8')
        except urllib2.URLError, e:
            if hasattr(e, 'reason'):
                print u'链接百度贴吧失败,错误原因:', e.reason
                return None

    def getTitle(self, page):
        pattern = re.compile('<h3 class="core_title_txt.*?>(.*?)</h3>', re.S)
        result = re.search(pattern, page)
        if result:
            # print result.group(1)
            return result.group(1).strip()
        else:
            print u'获取贴吧标题失败!'
            return None

    def getPageNum(self, page):
        pattern = re.compile('<li class="l_reply_num.*?red">(.*?)</span>', re.S)
        result = re.search(pattern, page)
        if result:
            # print result.group(1)
            return result.group(1).strip()
        else:
            print u'获取贴吧页数失败!'
            return None

    def getContent(self, page):
        pattern = re.compile('<div id="post_content.*?>(.*?)</div>', re.S)
        items = re.findall(pattern, page)
        contents = []
        for item in items:
            content = '\n'+self.tool.replace(item)+'\n'
            contents.append(content.encode('utf-8'))
        return contents

    def setFileTitle(self, title):
        if title is not None:
            self.file = open(title + '.txt', 'w+')
        else:
            self.file = open(self.defaultTitle + '.txt', 'w+')

    def writeData(self, contents):
        for item in contents:
            if int(self.floorTag) == 1:
                floorLine = '\n' + str(self.floor) + u'----------------------------------\n'
                # print floorLine
                self.file.write(floorLine)
            self.file.write(item)
            self.floor += 1

    def start(self):
        indexPage = self.getPage(1)
        pageNum = self.getPageNum(indexPage)
        title = self.getTitle(indexPage)
        self.setFileTitle(title)
        if pageNum == None:
            print "URL已失效,请重试"
            return
        try:
            print "该帖子共有".decode('utf-8').encode('gbk') + str(pageNum) + "页".decode('utf-8').encode('gbk')
            for i in range(1, int(pageNum)+1):
                print "正在写入第".decode('utf-8').encode('gbk') + str(i) + "页数据......".decode('utf-8').encode('gbk')
                page = self.getPage(i)
                contents = self.getContent(page)
                self.writeData(contents)
        except IOError, e:
            print "写入异常, 原因是:" + e.message
        finally:
            print "写入任务成功".decode('utf-8').encode('gbk')
            self.file.close()


print u"请输入帖子代号"
baseUrl = 'http://tieba.baidu.com/p/'+str(raw_input('http://tieba.baidu.com/p/'))
seeLZ = raw_input(unicode('是否获取楼主发言,是输入1,否输入0:', 'utf-8').encode('gbk'))
floorTag = raw_input(unicode('是否写入楼层信息,是输入1,否输入0:', 'utf-8').encode('gbk'))
bdtb = BDTB(baseUrl, seeLZ, floorTag)
bdtb.start()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值