范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Python爬虫实战二之爬取百度贴吧帖子

  本篇目标1. 对百度贴吧的任意帖子进行抓取
  2. 指定是否只抓取楼主发帖内容
  3. 将抓取到的内容分析并保存到文件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 方法。另外,获取页面的方法我们需要知道一个参数就是帖子页码,所以这个参数的指定我们放在该方法中。 综上,我们初步构建出基础代码如下: __author__ = "CQC" # -*- coding: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)             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,查看页面源代码,我们找到标题所在的代码段,可以发现这个标题的 HTML 代码是 

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

  所以我们想提取 标签中的内容,同时还要指定这个 class 确定唯一,因为 h1 标签实在太多啦。 正则表达式如下1(.*?)所以,我们增加一个获取页面标题的方法12345678910#获取帖子标题def getTitle(self):page = self.getPage(1)pattern = re.compile("2)提取帖子页数   同样地,帖子总页数我们也可以通过分析页面中的共?页来获取。所以我们的获取总页数的方法如下 #获取帖子一共有多少页 def getPageNum(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 None3)提取正文内容   审查元素,我们可以看到百度贴吧每一层楼的主要内容都在   标签里面,所以我们可以写如下的正则表达式 (.*?)   相应地,获取页面所有楼层数据的方法可以写成如下方法 #获取每一层楼的内容,传入页面内容 def getContent(self,page): pattern = re.compile("(.*?)",re.S) items = re.findall(pattern,page) for item in items: print item   好,我们运行一下结果看一下   真是醉了,还有一大片换行符和图片符,好口怕!既然这样,我们就要对这些文本进行处理,把各种各样复杂的标签给它剔除掉,还原精华内容,把文本处理写成一个方法也可以,不过为了实现更好的代码架构和代码重用,我们可以考虑把标签等的处理写作一个类。 那我们就叫它 Tool(工具类吧),里面定义了一个方法,叫 replace,是替换各种标签的。在类中定义了几个正则表达式,主要利用了 re.sub 方法对文本进行匹配后然后替换。具体的思路已经写到注释中,大家可以看一下这个类 import re #处理页面标签类 class Tool: #去除img标签,7位长空格 removeImg = re.compile("| {7}|") #删除超链接标签 removeAddr = re.compile("|") #把换行的标签换为 replaceLine = re.compile("|||") #将表格制表替换为 replaceTD= re.compile("") #把段落开头换为 加空两格 replacePara = re.compile("") #将换行符或双换行符替换为 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," ",x) x = re.sub(self.replaceTD," ",x) x = re.sub(self.replacePara," ",x) x = re.sub(self.replaceBR," ",x) x = re.sub(self.removeExtraTag,"",x) #strip()将前后多余内容删除 return x.strip()   在使用时,我们只需要初始化一下这个类,然后调用 replace 方法即可。 现在整体代码是如下这样子的,现在我的代码是写到这样子的 __author__ = "CQC" # -*- coding:utf-8 -*- import urllib import urllib2 import re #处理页面标签类 class Tool: #去除img标签,7位长空格 removeImg = re.compile("| {7}|") #删除超链接标签 removeAddr = re.compile("|") #把换行的标签换为 replaceLine = re.compile("|||") #将表格制表替换为 replaceTD= re.compile("") #把段落开头换为 加空两格 replacePara = re.compile("") #将换行符或双换行符替换为 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," ",x) x = re.sub(self.replaceTD," ",x) x = re.sub(self.replacePara," ",x) x = re.sub(self.replaceBR," ",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 getPageNum(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("(.*?)",re.S) items = re.findall(pattern,page) #for item in items: # print item print self.tool.replace(items[1]) baseURL = "http://tieba.baidu.com/p/3138733512" bdtb = BDTB(baseURL,1) bdtb.getContent(bdtb.getPage(1))   我们尝试一下,重新再看一下效果,这下经过处理之后应该就没问题了,是不是感觉好酸爽!   4)替换楼层   至于这个问题,我感觉直接提取楼层没什么必要呀,因为只看楼主的话,有些楼层的编号是间隔的,所以我们得到的楼层序号是不连续的,这样我们保存下来也没什么用。 所以可以尝试下面的方法: 1. 每打印输出一段楼层,写入一行横线来间隔,或者换行符也好。   2. 试着重新编一个楼层,按照顺序,设置一个变量,每打印出一个结果变量加一,打印出这个变量当做楼层。   这里我们尝试一下吧,看看效果怎样 把 getContent 方法修改如下 #获取每一层楼的内容,传入页面内容 def getContent(self,page): pattern = re.compile("(.*?)",re.S) items = re.findall(pattern,page) floor = 1 for item in items: print floor,u"楼------------------------------------------------------------------------------------------------------------------------------------ " print self.tool.replace(item) floor += 1   运行一下看看效果   嘿嘿,效果还不错吧,感觉真酸爽!接下来我们完善一下,然后写入文件 4. 写入文件   最后便是写入文件的过程,过程很简单,就几句话的代码而已,主要是利用了以下两句   file = open("tb.txt","w") file.writelines(obj)   这里不再赘述,稍后直接贴上完善之后的代码。 5. 完善代码   现在我们对代码进行优化,重构,在一些地方添加必要的打印信息,整理如下 __author__ = "CQC" # -*- coding:utf-8 -*- import urllib import urllib2 import re #处理页面标签类 class Tool: #去除img标签,7位长空格 removeImg = re.compile("| {7}|") #删除超链接标签 removeAddr = re.compile("|") #把换行的标签换为 replaceLine = re.compile("|||") #将表格制表替换为 replaceTD= re.compile("") #把段落开头换为 加空两格 replacePara = re.compile("") #将换行符或双换行符替换为 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," ",x) x = re.sub(self.replaceTD," ",x) x = re.sub(self.replacePara," ",x) x = re.sub(self.replaceBR," ",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 getPageNum(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("(.*?)",re.S) items = re.findall(pattern,page) contents = [] for item in items: #将文本进行去除标签处理,同时在前后加入换行符 content = " "+self.tool.replace(item)+" " 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 = " " + str(self.floor) + u"----------------------------------------------------------------------------------------- " 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,否输入0 ") floorTag = raw_input("是否写入楼层信息,是输入1,否输入0 ") bdtb = BDTB(baseURL,seeLZ,floorTag) bdtb.start()   现在程序演示如下   完成之后,可以查看一下当前目录下多了一个以该帖子命名的 txt 文件,内容便是帖子的所有数据。 抓贴吧,就是这么简单和任性!

  • 如果微信开始收费,每年的年费是500,你还会继续使用吗?凡是收费的,一定不会用!不管是微信还是扣扣!年费收入50元,我立即删除。没有微信时也活了半辈子。不会!我会直接给微信说拜拜!现在拥有微信这种功能的软件有很多!微信之所以成名是因为用有哪些极富美感的绿色手机壁纸?绿色给人的感觉为清新希望安全平静舒适生命和平宁静自然环保成长生机青春。绿色象征和平宁静自然。绿色的环境被誉为健康摇篮,因为它能调节神经系统,能放松视网膜,可治疗精神抑郁,消除紧张情现在入手佳能5D4如何?现在已经是2019年了,作为曾经的单反老大佳能在近些年来显得一身疲态,虽然5D4是一台很好的单反相机,但是也仅限于在佳能品牌中,如果用他的性能来对比尼康索尼5D4真心差的比较多,全大嘴余承东这次打了谁的脸?再次证明了这些民营企业的低俗趣味,哪怕如华为这么大的企业,一样是怼天怼地怼空气,拼命诋毁对手,所有车厂都不行,菊厂全宇宙第一,然后吹捧自己,菊厂才是宇宙的伟光正!其实,建议看看特斯截止到现在,你一共使用了几部手机?哪一部手机让你记忆犹新?截止目前为止,我一共用了十六部手机。我使用的所有手机中,诺基亚手机让我不能忘怀。诺基亚手机最大的优点就是很结实,像石头砖头一样坚硬,不怕碰不怕摔。记得有一次在家里吃核桃,找不到工具你怎么看激光电视取代液晶电视?很多80后小的时候总是喜欢看电视。那时候CRT电视是客厅主流,从黑白电视机到彩色电视机,很多人的童年里都离不开CRT设备的身影,而现在的小朋友已经不太喜欢看电视,他们的童年记忆已经杀出国门,走向世界,有哪些为国争光的入侵动物?中国大闸蟹入侵吓坏德国损失高达8000万欧元好吧,上面只是条赚眼球的新闻,下面开始正文。先说明一下,入侵这个概念还包含了不小心引入对当地生态环境造成影响和破坏等含义,但影响和破坏这AxonFrameworkevent调度器事件发布可以源自AxonFramework应用程序中的几个位置。一般来说,这些可以分为两个主要区域从聚合中调度事件,以及从常规组件调度事件本篇将描述如何从两个位置获取事件总线上的事数字货币妖股金财互联1公司的主营业务是热处理icon设备的研发生产和销售,以及专业热处理加工服务互联网财税服务。2公司是一家在电子税务和财税云服务等领域的领先企业。3该股强势的概念有区块链云计算跨境电李群李代数简介作者胡竭末编辑TraderJoes对称性在现代物理中占据核心地位,而描述对称性最有力的工具就是群论。在本文我们将简单介绍一种特殊的群李群。物理上经常会遇到一些能连续变化的对称性,为东数西算启动,关注IDC龙头股国家发改委联合其他部门发布了一个很有创意的工程,东数西算。不了解的百度一下。其实就是把东部的数据计算厂房移到了西部。这样做有三个好处一是电便宜二是厂房租金便宜三是引导高端人才向西部
    买投影仪还是大屏幕电视?分界线是一万,因为红米98寸的定价就是一万,且不论效果如何,在这里想说的是如果想要液晶电视有大屏的观影体验,预算是一万起步的。在这个价格之下,想要大屏的体验,可能就得考虑使用投影仪净水器十大名牌现在,随着人们生活水平的提高,越来越多的家庭不再满足于家庭硬装,而是将目光放在了能够提升生活健康水平的家装项目上,净水器就在这样的风潮当中走入了千家万户。但是现在销售净水器的品牌太荣耀30更新鸿蒙系统2。0。0。165版本,小伙伴们赶紧下载升级哦荣耀30更新HarmonyOS2。0。0145版本已有好长时间了,上周有其他版本手机更新了最新的165版本,我心激动,赶紧去试了试,结果没有捂脸有点失望!今天终于推送了更新,赶紧下iOS15Beta6发布,功能增删抢先看苹果在今天凌晨向全体开发者用户发布了以下系统更新iOS15beta6(19A5325f)iPadOS15beta6(19A5325f)tvOS15beta6(19J5332e)wa大屏观赛才够爽!推荐七款3000元价位平板电视如今的电视越来越智能,价格也跟着猛涨。但大多数人还是会选择3000元价位的电视,画质功能等能满足使用需求,价格也能接受。下面推荐几款定位3K档位的平板电视,在各方面表现都很出色,性2021年上半年六大拍照手机闭着眼跟着买就对今天,我就来为大家盘点一下2021年上半年的十大拍照手机(产品发布时间为2021年1月至今)。如果各位感兴趣的话,不妨跟着我一起来感受一下这十款手机的拍照魅力。以下产品不分排名先后国产手机谁是卷王?太好看了,我说的是iQOO产品经理宋姐姐。如果你没看过,肯定见过。这个产品一发布,这个姐姐一登场,那全场真是嗨爆了!以至于人家根本就没有关心发布会到底是什么产品鼾睡害羞结果呢,其他苏宁818战报出炉小米夺冠无悬念,华为表现令人尊敬如果说618属于京东,双11属于天猫,那么818肯定就是属于苏宁的。作为线上最大电商平台之一,看着京东618天猫双11玩得那么嗨,苏宁当然不会落后就搞出一个818狂欢节。在2021好用的手机桌面便签app下载哪款?在人们使用手机的时候,经常会碰到各种各样的软件app,通过下载安装它们,就可以获得不同的功能。便签app是很多人都在使用的一种辅助工具,其中手机桌面便签app尤为受欢迎,好用的手机小米MIX4搭载的UWB技术是什么?为何它可能会颠覆智能家居行业?在小米十一周年的雷军年度演讲大会上,小米发布了时隔3年之久的小米MIX4手机,除了采用了前沿的屏下摄像头技术以外,还首次搭载了UWB技术。对于大部分人来说,UWB技术可以说十分的陌ROG新机还能这么玩?差评体验官现场演示个性视窗以及双腰键体验8月18日晚,ROG召开了ROG电音潮玩夜活动,正式带来了2021下半年的新旗舰ROG游戏手机5sPro,在外观配置屏幕以及操控等方面都作出了一定程度的更新。值得一提的是,此次RO