大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子。与上一篇不同的是,这次我们需要用到文件的相关操作。

本篇目标对百度贴吧的任意帖子进行抓取

指定是否只抓取楼主发帖内容

将抓取到的内容分析并保存到文件

1. URL格式的确定

首先,我们先观察一下百度贴吧的任意一个帖子。

比如:http://tieba.baidu.com/p/3138733512?see_lz=1&pn=1,这是一个关于NBA50大的盘点,分析一下这个地址。

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

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

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

see_lz 和 pn 是该 URL 的两个参数,分别代表了只看楼主和帖子页码,等于1表示该条件为真

所以我们可以把URL分为两部分,一部分为基础部分,一部分为参数部分。

例如,上面的URL我们划分基础部分是 http://tieba.baidu.com/p/3138733512,参数部分是 ?see_lz=1&pn=1

2. 页面的抓取

熟悉了URL的格式,那就让我们用urllib2库来试着抓取页面内容吧。上一篇糗事百科我们最后改成了面向对象的编码方式,这次我们直接尝试一下,定义一个类名叫BDTB(百度贴吧),一个初始化方法,一个获取页面的方法。

其中,有些帖子我们想指定给程序是否要只看楼主,所以我们把只看楼主的参数初始化放在类的初始化上,即init方法。另外,获取页面的方法我们需要知道一个参数就是帖子页码,所以这个参数的指定我们放在该方法中。

综上,我们初步构建出基础代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26#-*-coding:utf8-*-

#created by 10412

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)

print response.read()

return response

except urllib2.URLError, e:

if hasattr(e, "reason"):

print u"连接百度贴吧失败,错误原因",e.reason

return None

baseURL = 'http://tieba.baidu.com/p/3138733512'

bdtb = BDTB(baseURL, 1)

bdtb.getPage(1)

运行代码,我们可以看到屏幕上打印出了这个帖子第一页楼主发言的所有内容,形式为HTML代码。

3. 提取相关信息

1)提取帖子标题

在浏览器中审查元素,或者按F12,查看页面源代码,我们找到标题所在的代码段如下:

1

纯原创我心中的NBA2014-2015赛季现役50大

所以我们要提取

中的内容,因为一开始可以查看整个界面的原代码,查看里面含有

标签的不止一个。所以需要写正则表达式来匹配,如下:

1

(.*?)

', re.S)

result = re.search(pattern, page)

if result:

# print result.group(1) #测试输出

return result.group(1).strip()

else:

return None

2)提取帖子页数

同样地,帖子总页数我们也可以通过分析页面中的共?页来获取。

1

4784回复贴,共 36页

所以我们的获取总页数的方法如下

1

2

3

4

5

6

7

8

9

10def (self):

page = self.getPage(1)

pattern = re.compile('

(.*?)

所以提取正文内容的方法:

1

2

3

4

5

6#获取每一层楼的内容,传入页面内容

def getContent(self,page):

pattern = re.compile('

可以看到有很多的换行符和图片符,既然出现这样的情况,那肯定不是我们想要的结果。那我们就必须要将文本进行处理,将各种复杂的标签给剔除,还原帖子的原来面貌。可以使用一个方法或者类将这个处理文本的实现,不过为了更好的代码重用和架构,还是建议使用一个类。

我们将这个类命名为Too(工具类),里面定义一个replace方法,替换各种标签。然后在类中定义几个正则表达式,利用re.sub方法对文本进行匹配后然后替换。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27import re

#处理页面标签类

class Tool:

#去除img标签,7位长空格

removeImg = re.compile('| {7}|')

#删除超链接标签

removeAddr = re.compile('|')

#把换行的标签换为n

replaceLine = re.compile('

|

|

|')

#将表格制表

替换为t

replaceTD= re.compile('

')

#把段落开头换为n加空两格

replacePara = re.compile('

')

#将换行符或双换行符替换为n

replaceBR = re.compile('

|
')

#将其余标签剔除

removeExtraTag = 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.replacePara,"n ",x)

x = re.sub(self.replaceBR,"n",x)

x = re.sub(self.removeExtraTag,"",x)

#strip()将前后多余内容删除

return x.strip()

在使用时,我们只需要初始化一下这个类,然后调用replace方法即可。

现在整体代码是如下这样子的,现在我的代码是写到这样子的:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79#-*-coding:utf8-*-

#created by 10412

import urllib

import urllib2

import re

# 处理页面标签类

class Tool:

# 去除img标签,7位长空格

removeImg = re.compile('| {7}|')

# 删除超链接标签

removeAddr = re.compile('|')

# 把换行的标签换为n

replaceLine = re.compile('

|

|

|')

# 将表格制表

替换为t

replaceTD = re.compile('

')

# 把段落开头换为n加空两格

replacePara = re.compile('

')

# 将换行符或双换行符替换为n

replaceBR = re.compile('

|
')

# 将其余标签剔除

removeExtraTag = 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.replacePara, "n ", x)

x = re.sub(self.replaceBR, "n", x)

x = re.sub(self.removeExtraTag, "", x)

# strip()将前后多余内容删除

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)

return response.read().decode('utf-8')

except urllib2.URLError, e:

if hasattr(e, "reason"):

print u"连接百度贴吧失败,错误原因", e.reason

return None

# 获取帖子标题

def getTitle(self):

page = self.getPage(1)

pattern = re.compile('

.*?(.*?)', re.S)

result = re.search(pattern, page)

if result:

# print result.group(1) #测试输出

return result.group(1).strip()

else:

return None

# 获取每一层楼的内容,传入页面内容

def getContent(self, page):

pattern = re.compile('

4)替换楼层

至于这个问题,我感觉直接提取楼层没什么必要呀,因为只看楼主的话,有些楼层的编号是间隔的,所以我们得到的楼层序号是不连续的,这样我们保存下来也没什么用。

所以可以尝试下面的方法:

1.每打印输出一段楼层,写入一行横线来间隔,或者换行符也好。

2.试着重新编一个楼层,按照顺序,设置一个变量,每打印出一个结果变量加一,打印出这个变量当做楼层。

将getContent方法修改如下:

1

2

3

4

5

6

7

8

9#获取每一层楼的内容,传入页面内容

def getContent(self,page):

pattern = re.compile('

print self.tool.replace(item)

floor += 1

运行结果截图如下:

4. 写入文件

代码:

1

2file = open(“tb.txt”,”w”)

file.writelines(obj)

5. 完善代码1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134#-*-coding:utf8-*-

#created by 10412

import urllib

import urllib2

import re

#处理页面标签类

class Tool:

#去除img标签,7位长空格

removeImg = re.compile('| {7}|')

#删除超链接标签

removeAddr = re.compile('|')

#把换行的标签换为n

replaceLine = re.compile('

|

|

|')

#将表格制表

替换为t

replaceTD= re.compile('

')

#把段落开头换为n加空两格

replacePara = re.compile('

')

#将换行符或双换行符替换为n

replaceBR = re.compile('

|
')

#将其余标签剔除

removeExtraTag = 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.replacePara,"n ",x)

x = re.sub(self.replaceBR,"n",x)

x = re.sub(self.removeExtraTag,"",x)

#strip()将前后多余内容删除

return x.strip()

#百度贴吧爬虫类

class BDTB:

#初始化,传入基地址,是否只看楼主的参数

def __init__(self,baseUrl,seeLZ,floorTag):

#base链接地址

self.baseURL = baseUrl

#是否只看楼主

self.seeLZ = '?see_lz='+str(seeLZ)

#HTML标签剔除工具类对象

self.tool = Tool()

#全局file变量,文件写入操作对象

self.file = None

#楼层标号,初始为1

self.floor = 1

#默认的标题,如果没有成功获取到标题的话则会用这个标题

self.defaultTitle = u"百度贴吧"

#是否写入楼分隔符的标记

self.floorTag = floorTag

#传入页码,获取该页帖子的代码

def getPage(self,pageNum):

try:

#构建URL

url = self.baseURL+ self.seeLZ + '&pn=' + str(pageNum)

request = urllib2.Request(url)

response = urllib2.urlopen(request)

#返回UTF-8格式编码内容

return response.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('

.*?(.*?)',re.S)

result = re.search(pattern,page)

if result:

return result.group(1).strip()

else:

return None

#获取每一层楼的内容,传入页面内容

def getContent(self,page):

#匹配所有楼层的内容

pattern = re.compile('

contents.append(content.encode('utf-8'))

return contents

def setFileTitle(self,title):

#如果标题不是为None,即成功获取到标题

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 self.floorTag == '1':

#楼之间的分隔符

floorLine = "n" + str(self.floor) + u"-----------------------------------------------------------------------------------------n"

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 "该帖子共有" + str(pageNum) + "页"

for i in range(1,int(pageNum)+1):

print "正在写入第" + str(i) + "页数据"

page = self.getPage(i)

contents = self.getContent(page)

self.writeData(contents)

#出现写入异常

except IOError,e:

print "写入异常,原因" + e.message

finally:

print "写入任务完成"

print u"请输入帖子代号"

baseURL = 'http://tieba.baidu.com/p/' + str(raw_input(u'http://tieba.baidu.com/p/'))

seeLZ = raw_input("是否只获取楼主发言,是输入1,否输入0n")

floorTag = raw_input("是否写入楼层信息,是输入1,否输入0n")

bdtb = BDTB(baseURL,seeLZ,floorTag)

bdtb.start()

运行后截图如下:

备注:运行后注意输入帖子的代号先在网址后空格,再输入帖子代号,输入完再把刚才的空格

删除,只有这样才不会报错。

Traceback (most recent call last):

File “E:/python/code/PycharmProject/Python-Projects/baidutieba/BDTB3.py”, line 149,

in < module >

bdtb.start()

File “E:/python/code/PycharmProject/Python-Projects/baidutieba/BDTB3.py”, line 123, in start

pageNum = self.getPageNum(indexPage)

File “E:/python/code/PycharmProject/Python-Projects/baidutieba/BDTB3.py”, line 86, in getPageNum

result = re.search(pattern,page)

File “C:Python27libre.py”, line 146, in search

return _compile(pattern, flags).search(string)

TypeError: expected string or buffer

python爬百度贴吧_Python爬虫实战之爬取百度贴吧帖子相关推荐

  1. python爬取汽车之家_python爬虫实战之爬取汽车之家网站上的图片

    随着生活水平的提高和快节奏生活的发展.汽车开始慢慢成为人们的必需品,浏览各种汽车网站便成为购买合适.喜欢车辆的前提.例如汽车之家网站中就有最新的报价和图片以及汽车的相关内容,是提供信息最快最全的中国汽 ...

  2. python爬虫爬取百度图片总结_python爬虫如何批量爬取百度图片

    当我们想要获取百度图片的时候,面对一张张图片,一次次的点击右键下载十分麻烦.python爬虫可以实现批量下载,根据我们下载网站位置.图片位置.图片下载数量.图片下载位置等需求进行批量下载,本文演示py ...

  3. python实例豆瓣音乐代码_Python爬虫实战(3)-爬取豆瓣音乐Top250数据(超详细

    前言 首先我们先来回忆一下上两篇爬虫实战文章: 第一篇:讲到了requests和bs4和一些网页基本操作. 第二篇:用到了正则表达式-re模块 今天我们用lxml库和xpath语法来爬虫实战. 1.安 ...

  4. python爬虫经典段子_Python爬虫实战之爬取糗事百科段子

    首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来. 友情提示 糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的 ...

  5. go爬虫和python爬虫哪个好_python 爬虫实战项目--爬取京东商品信息(价格、优惠、排名、好评率等)-Go语言中文社区...

    利用splash爬取京东商品信息 一.环境 window7 python3.5 pycharm scrapy scrapy-splash MySQL 二.简介 为了体验scrapy-splash 的动 ...

  6. python爬虫爬图片教程_python爬虫实战之爬取京东商城实例教程

    前言 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1. ...

  7. python爬虫爬取教程_python爬虫实战之爬取京东商城实例教程

    前言 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1. ...

  8. python安卓手机爬虫_python爬虫实战之爬取安卓apk

    当前市面上有大量的应用市场,这些应用市场作为各个安卓开发者的分发渠道,占据着重要的位置.如果我们需要批量下载apk用于研究,那么就需要用到爬虫技术,这里仅仅介绍一个简单的例子,即爬取应用宝上的apk. ...

  9. 尹成python爬虫百度云_Python爬虫实战:抓取并保存百度云资源

    寻找并分析百度云的转存api 首先你得有一个百度云盘的账号,然后登录,用浏览器(这里用火狐浏览器做示范)打开一个分享链接.F12打开控制台进行抓包.手动进行转存操作:全选文件->保存到网盘-&g ...

最新文章

  1. 深度学习中的问题汇总(持续更新...)
  2. Java 地下迷宫·算法·(ACM/蓝桥杯)·递归解法
  3. Spring Boot war方式打包发布
  4. .NET下 Access与SQL Server的效率简易比较
  5. zoj2587唯一最小割
  6. jupyterlab nb_conda 增加 删除_Jupyter lab
  7. java上传图片裁剪_浅谈java图片上传之剪切
  8. Python Tkinter教程(一)——tkinter编程基本步骤、窗口基本属性及Toplevel控件的使用
  9. 最新Apple苹果开发者账号AppleID注册流程
  10. 推荐一些经典的学习书籍
  11. addition过程 sgnb_5G-NSA接入流程分析及问题定位四步法
  12. 利用python进行识别相似图片(一)
  13. 〖Python自动化办公篇⑬〗- Excel 文件自动化 - 写入 excel 数据(xlsxwriter)
  14. 琴生不等式(Jensen Inequality)
  15. 白噪声校验matlab,白噪声的测试MATLAB程序.doc
  16. linux之cut的使用
  17. 轻松学会WiFi模块(ESP8266)—基于STM32,学到就是赚到!
  18. 火狐浏览器不能添加和修改书签
  19. 【WindowXP】net use 系统错误64
  20. 新大西洋海底光缆:传输速度达160Tbps

热门文章

  1. 曲速未来 披露:对加密货币交换gate.io供应链攻击
  2. pycharm换黑皮肤
  3. 在用户同意隐私政策前,您的应用获取了用户的ANDROID ID,不符合华为应用市场审核标准。
  4. 购买Microsoft Technet订阅,免费获得微软几乎所有的产品序列号“用于评估”,...
  5. Sqlserver的convert函数
  6. Spring Boot配置文件及配置绑定(三)
  7. Nancy总结(一)Nancy一个轻量的MVC框架
  8. 全彩色LED灯带中应用到的LED炫彩灯
  9. 创新数据基础设施高峰论坛,构建安全高效的城市智慧底座 ​
  10. Linux网络服务_apache阿帕奇