python爬取百度贴吧的帖子

      最近看到一篇这样的帖子,学习一下。

目的:抓取百度贴吧某一篇帖子的内容(包括帖子名称,页数,及内容),并对内容进行筛选处理。

一、URL格式的确定

我们观察一下百度贴吧的任意一个帖子:https://tieba.baidu.com/p/3138733512?see_lz=1&pn=1,分析一下这个地址:

1)http:// 代表资源传输使用http协议

2)tieba.baidu.com是百度的二级域名,指向百度贴吧的服务器

3)/p/3138733512是服务器摸个资源,即这个帖子的地址定位符

4)see_lz和pn是该URL的两个参数,分别代表了只看楼主(1代表为真,0为假)和帖子页码。

      我们把URL分为基础部分和参数部分,这个URL的基础部分为https://tieba.baidu.com/p/3138733512,参数部分为?see_lz=1&pn=1

二、抓取网页的html

# -*- coding: gbk -*-  #我用utf-8显示不出中文,不知道怎么回事
import urllib
import urllib2
import re


class BDTB:
    def __init__(self,baseURL,seeLZ): #定义变量
        self.baseURL = baseURL
        self.seeLZ = '?see_lz='+str(seeLZ)
    def getPage(self,pageNum):
        try:
            url = self.baseURL + self.seeLZ + "&pn=" + str(pageNum)
            request = urllib2.Request(url)
            response = urllib2.urlopen(request)
            return response.read() #返回页面的html
        except urllib2.URLError,e:

#当urlopen不能够处理一个request的时候,会产生一个URLError,URLError通常在没有网络连接,或者服务器不存在的情况下产生,这种情况下,异常通常带有“reason”属性,它是一个tuple,包含了一个错误号和一个错误信息。
            if hasattr(e,"reason"):

# hasattr(object,name)判断一个对象是否有name属性或name方法,返回BOOL值;有name特性返回True,否则返回False
                print "链接错误,原因" ,e.reason
                return None

baseURL = "http://tieba.baidu.com/p/3138733512"
bdtb = BDTB(baseURL,1)

三、提取相关信息

1)提取帖子标题:

 def getTitle(self):
        page = self.getPage(1)
        reg = '<title>(.*?)</title>'
        pattern = re.compile(reg)
        result = re.search(pattern,page)
        if result:
            print result.group(1)

#group(0)和group()就是匹配正则表达式整体结果,group(1)列出第一个括号匹配部分,group(2)列出第二个括号匹配部分,group(3)列出第三个括号匹配部分,注意这里如果不添加group()就不会输出结果,所有我猜想应该是re.search()所必须的。
        else:
            print "error"

2)提取帖子页数:

def getPageNum(self):
        page = self.getPage(1)
        reg = r'<li class="l_reply_num" style="margin-left:8px" >'
        reg += '<span class="red" style="margin-right:3px">(.*)'
        reg += '</span>.*?<span class="red">(.*?)</span>(.*?)</li>'
        pattern = re.compile(reg)
        result = re.search(pattern,page)
        if result:
            print result.group(2)
        else:
            print None

3)提取正文内容:

 def getSentance(self):
        page= self.getPage(1)
        reg = r'<div id="post_content_.*?" class="d_post_content j_d_post_content ">'
        reg += '[\s]*(.*?)</div>'
        pattern = re.compile(reg)
        items = re.findall(pattern,page)
        for item in items:
            print item

这个时候运行程序

baseURL = "http://tieba.baidu.com/p/3138733512"
bdtb = BDTB(baseURL,1)

bdtb.getSentance()

就会发现输出来一大锥内容,还包含图片代码什么乱七八糟的,所以下面就要进行这节课最有意思的一部分,就是剔除杂乱信息——处理页面标签。

4)处理页面标签:**********************************

      我们把标签的处理写到单独一个类里边,这样更方便以后的处理;在类中定义了一个方便,用来替换要处理的标签,我们用re.sub()方法来替换要处理的标签。

class Tool:
    removeImg = re.compile("<img.*?>") #去除img标签,也就是图片部分
    removeAddr = re.compile("<a.*?>|</a>") #删除超链接标签

#这里说一下,在html中,超链接的标签是:<a href="URL">超链</a>
    replaceLine = re.compile("<tr>|<div>|</div>|</p>") #把换行的标签换为\n
    replaceTD = re.compile("<td>") #把表格制表<td>替换为\t
    replaceBR = re.compile("<br><br>|<br>") #把换行符或双换行符替换为\n。<br>是分行
    replacePara = re.compile('<p.*?>') # 把段落开头替换为\n加空两格,这里好像用不上
    removeExist = re.compile("<.*?>") #将其余标签剔除
    def replace(self,x):
        x = re.sub(self.removeImg,"",x) #用re.sub()方法替换上面正则表达式对应的段落中的html。
        x = re.sub(self.removeAddr,"",x)
        x = re.sub(self.replaceLine,"\n",x)
        x = re.sub(self.replaceTD,"\t",x)        
        x = re.sub(self.replaceBR,"\n",x)
        x = re.sub(self.replacePara,"\n    ",x)
        x = re.sub(self.removeExist,"",x)

# re.sub(pattern,replacement,string),pattern是正则表达式中的模式字符串,replacement是要被替换进去的字符串,string是要被替换一部分的整个字符串。
        return x.strip() #strip()将字符串前后空格删除

说明一下,这里是给出了几种替换方法,根据实际需要选择相应的替换方法,当然自己也可以随意选择其他方法替换。

这样的话,整体代码就可写为:

class Tool:
    removeImg = re.compile("<img.*?>")
    removeAddr = re.compile("<a.*?>|</a>") #正则表达式中的竖杠(|)是或者的意思。
    replaceLine = re.compile("<tr>|<div>|</div>|</p>")
    replaceTD = re.compile("<td>")
    replaceBR = re.compile("<br><br>|<br>")
    replacePara = re.compile('<p.*?>')
    removeExist = re.compile("<.*?>")
    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.replaceBR,"\n",x)
        x = re.sub(self.replacePara,"\n    ",x)
        x = re.sub(self.removeExist,"",x)
        return x.strip() 
class BDTB:
    def __init__(self,baseURL,seeLZ):
        self.baseURL = baseURL
        self.seeLZ = '?see_lz='+str(seeLZ)
        self.tool = Tool()
    def getPage(self,pageNum):
        try:
            url = self.baseURL + self.seeLZ + "&pn=" + str(pageNum)
            request = urllib2.Request(url)
            response = urllib2.urlopen(request)
            #print response.read()
            return response.read()
        except urllib2.URLError,e:
            if hasattr(e,"reason"):
                print "链接错误,原因" ,e.reason
                return None
    def getTitle(self):
        page = self.getPage(1)
        reg = '<title>(.*?)</title>'
        pattern = re.compile(reg)
        result = re.search(pattern,page)
        if result:
            print result.group(1)
        else:
            print "error"
    def getPageNum(self):
        page = self.getPage(1)
        reg = r'<li class="l_reply_num" style="margin-left:8px" >'
        reg += '<span class="red" style="margin-right:3px">(.*)'
        reg += '</span>.*?<span class="red">(.*?)</span>(.*?)</li>'
        pattern = re.compile(reg)
        result = re.search(pattern,page)
        if result:
            print result.group(2)
        else:
            print None
    def getSentance(self):
        page= self.getPage(1)
        reg = r'<div id="post_content_.*?" class="d_post_content j_d_post_content ">'
        reg += '[\s]*(.*?)</div>'
        pattern = re.compile(reg)
        items = re.findall(pattern,page)
        for item in items:
            print self.tool.replace(item)

5)手动添加楼层并存入txt文件:

我们把函数getSentance()改一下:

def getSentance(self):
        page= self.getPage(1)
        reg = r'<div id="post_content_.*?" class="d_post_content j_d_post_content ">'
        reg += '[\s]*(.*?)</div>'
        pattern = re.compile(reg)
        items = re.findall(pattern,page)
        floor = 1
        contents = []
        fileName = open("nba.txt",'w')
        for item in items:
            floorLine = "\n\n" + str(floor) + "----------------------------\n"
            content = self.tool.replace(item)
            contents.append(floorLine)
            contents.append(content)
            floor += 1
        for content in contents:
            fileName.write(content)

baseURL = "http://tieba.baidu.com/p/3138733512"
bdtb = BDTB(baseURL,1)
bdtb.getSentance()

这样就可以运行程序了。

    其实这个程序还存在一些问题:

1)写入文件应该再单独编写一个函数

2)文件的标题应该把getTitle()的结果加上,但是因为getTitle()的结果是汉语,网上给了一些方法,我的python2.7版本试了几次都没成功,所以暂时存疑。






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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值