现在的位置: 主页 > 主打产品 > 文章列表

python 爬虫实战 抓取学校bbs相关板块的发帖信息

作者:程力专用汽车股份有限公司 来源:www.dfclxwc.com 未知发布时间:2017-09-06 10:01:11
python 爬虫实战 抓取学校bbs相关板块的发帖信息

之前也因为感兴趣, 写过一个抓取桌面天空里面喜欢的动漫壁纸的爬虫代码。这两天突然看到有人写了这么一篇文章: 爬取京东本周热卖商品基本信息存入MySQL
觉得蛮有趣的, 正好临近找工作的季节, 就想着能不能写个爬虫, 把咱们学校bbs上面相关的板块里面的发帖信息给记录下来。

2. 项目分析 首先我们打开我们的目标网页

这里写图片描述


结果我们发现, 进入到job板块之后, 还是没有找到网页的源码信息,ie, 我们没有找到他的真正的网页地址。我们一开始猜想我们的bbs 应该是使用post方式, 利用js 异步获取网页数据的, 然而, 当我们进入Network功能查看的时候, 发现他实际上还是使用了 GET 方式, 只不过他的真实地址被隐藏了而已

这里写图片描述


上面用红框框圈出来的地址就是Job 板块的真实地址了

这里写图片描述


然后我们就可以方便的找到我们的真实地址以及网页源码了

这里写图片描述


由于, 我们学校的bbs上面回帖信息一般都不咋地, 于是这里, 我们直接忽略他
得到不含回帖信息的url ?type=1&board=Job&title=&title2=&title3=&userid=&dt=7&og=on&boardordigest=0&labelabc=0

我们发现真正需要变化的是 Job 部分, 将Job 改成 Intern 可以得到实习板块的相关信息。
然后我们查看网页的源码:

这里写图片描述


由于我们需要得到作者, 日期, 帖子的连接地址, 标题 这四个信息, 很容易分析得到我们所需要使用的正则表达式:

string = "author.*?>(.*?).*?datetime.*?>(.*?)<.*?title.*?(.*?)"

其中第三项得到我们帖子的相应地址, 同样可以分析得到提取帖子内容的正则表达式为:

pattern_str = "WWWPOST(.*?) --"

这里写图片描述

至此, 基本分析完毕

3. 编写过程中遇到的一些坑 在re.findall 的地方, 发生假死
这个里面具体原因在于我们的正则表达式没有能够一开始就匹配成功, 导致进入死循环, 修正正则表达式即可 中文字节码输出u’\u5357\u4eac\u5fb7\u552f\u601d\u7eba\u7ec7\u54c1
这个并不是错误, 但是很讨厌, 他只是输出字节码, 而且这个现象时有时无, 在出现这个问题的时候, 我们可以在相应的 str 后面加上 decode("utf?8")即可正常输出中文了

UnicodeDecodeError:‘XXX’ codec can’t decode bytes in position错误信息解 决办法
inStr2=inStr.decode(‘utf?8',‘ignore′) 加一个ignore 参数就可以了

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position。。

解决方法

有两种办法可以解决 1.换成python 3.x 2.在代码前面加上 import sys reload(sys) sys.setdefaultencoding('utf-8')

cmd 窗口大小调节

这里写图片描述

cmd 窗口乱码问题

这里写图片描述


我们的代码在eclipse 的console 中正常显示, 但是到了cmd中就中文乱码了, 这里的解决方案是: 将输出字符全部encode 成 gb2312 4. 运行效果

这里写图片描述

5. code # -*- coding:utf-8 -*- ''' Created on 2016-5-2 获取 BBS 相关板块的信息 @author: ThinkPad User ''' import sys reload(sys) sys.setdefaultencoding('utf8') import urllib import urllib2 import re class BBSSpider: ''' classdocs ''' def __init__(self): #self.baseURL = "?board=" + str(board) self.baseURL = "" self.enable = True self.charaterset = "gb2312" # 获取最近不含回帖的帖子 def getHtml(self, url): #self.baseURL = "?type=1&board=" + str(board) + "&title=&title2=&title3=&userid=&dt=7&og=on&boardordigest=0&labelabc=0" self.baseURL = url try: request = urllib2.Request(self.baseURL) response = urllib2.urlopen(request) #print response.read().decode(self.charaterset, 'ignore') return response.read().decode("gb2312", 'ignore').encode("utf-8") except urllib2.URLError, e: if hasattr(e, "reason"): string = "连接bbs 失败, 原因" + str(e.reason) print string.encode(self.charaterset) return None # 删除 获取的网页内容中的一些噪声 def removeNoise(self, content): # 去除 removeNBSP = re.compile(r"") content = re.sub(removeNBSP, " ", content).strip() removeAMP = re.compile(r"&") content = re.sub(removeAMP, "&", content).strip() removeBR = re.compile(r" ") content = re.sub(removeBR, "\n", content).strip() # remove blank line removeN = re.compile(r"\n{1,}") content = re.sub(removeN, "\n", content).strip() return content # 获取发帖信息 def getItem(self, board): string = "?type=1&board=" + str(board) + "&title=&title2=&title3=&userid=&dt=7&og=on&boardordigest=0&labelabc=0" content = self.getHtml(string) if not content: print "加载页面失败" return #string = r"author.*?>(.*?).*?datetime.*?>(.*?)<.*?title>(.*?)" string = r"author.*?>(.*?).*?datetime.*?>(.*?)<.*?title.*?(.*?)" pattern = re.compile(string, re.S) res = re.findall(pattern, content) stories = [] count = 0 for item in res: text = self.removeNoise(item[3]) stories.append(item[2]) # 获取内容 string_out = str("id:%3d\t发帖人:%20s\t发帖时间:%20s\t发帖标题:%40s" % (count, item[0], item[1], text)) print string_out.encode(self.charaterset) count += 1 return stories # 获取详细信息 def getDetails(self, board): stories = self.getItem(board) if not stories: return total_num = len(stories) while self.enable: string_tip = str("\n\n================【请输入需要查看的帖子的id, 按 Q 退出】==============").encode(self.charaterset) id = raw_input(string_tip) if id == "Q": self.enable = False break try: int_id = int(id) if int_id < 0 or int_id >= total_num: continue except: continue string = "" + stories[int_id] content = self.getHtml(string) if not content: print "获取网页信息失败" return pattern_str = "WWWPOST(.*?) --" pattern = re.compile(pattern_str, re.S) res = re.findall(pattern, content) for item in res: text = self.removeNoise(item) print text.encode(self.charaterset) # 使用常用板块信息 def getBoard(self): flag = True self.enable = True boards = ['Job', 'Intern', 'SecondHand', 'PieBridge', 'Free', 'PMPI', 'Badminton', 'Swimming'] count = 0 for item in boards: print "id:%d board:%15s" % (count, boards[count]) count += 1 total_num = count while flag: self.enable = True string_tip = str("\n\n===================【请输入需要查看的板块的id, 按 Q 退出】================").encode(self.charaterset) id = raw_input(string_tip) if id == "Q": flag = False break try: int_id = int(id) if int_id < 0 or int_id >= total_num: continue except: continue self.getDetails(boards[int_id]) if "__main__" == __name__: bbs = BBSSpider() bbs.getBoard() #bbs.getDetails("Job")

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:武汉SEO http://wuhan.raoyu.net

上一篇:九网联盟 与您共赢天下 下一篇:最后一页