Python爬虫实践笔记(二)

xiaoxiao2021-02-28  125

无登录百度贴吧的帖子

基本步骤: ①分析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()
转载请注明原文地址: https://www.6miu.com/read-24132.html

最新回复(0)