版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27283619/article/details/88579720
注意:正则匹配好笑数和评论数有问题,这两天我抽时间重新试试,有好的可行方案的小伙伴可以在评论区指出,谢谢!
一、目标
- 抓取糗事百科上的段子
- 实现每按一次回车显示一个段子的页数、发布人,好笑数,评论数,内容。
二、设计思路
本爬虫是基于崔庆才大佬的博客迁移而来,可以说是用python3把原教程重新实现了一次。具体过程参照点这里
主要的改变在于:
- 删去了过滤图片的部分代码,因为网站发生了变化,所以直接匹配文字评论,没有提取图片。
- 用的是Python3中的urllib库,原教程是基于python2.7版本
三、直接上代码
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 15 07:24:39 2019
@author: Jock
"""
import urllib
import re
# 定义糗事百科爬虫类
class QSBK:
# 初始化方法,定义一些变量
def __init__(self):
self.page_index = 1
self.user_agent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
# 初始化headers
self.headers = {'User-Agent':self.user_agent}
# 存放段子的变量,每一个元素是每一页的段子们
self.stories = []
# 存放程序是否继续运行的变量
self.enable = False
# 传入某一页的索引获得页面代码
def get_page(self,page_index):
try:
url = 'http://www.qiushibaike.com/hot/page/' + str(page_index)
# 构建request请求
req = urllib.request.Request(url, headers=self.headers)
# 利用urlopen获取页面代码
response = urllib.request.urlopen(req)
# 将页面转化为UTF-8编码
page_code = response.read().decode('utf-8')
return page_code
except urllib.request.URLError as e:
if hasattr(e,"reason"):
print("连接糗事百科失败,错误原因:", e.reason)
return None
# 传入某一页代码,返回本页不带图片的段子列表
def get_page_items(self, page_index):
page_code = self.get_page(page_index)
if not page_code:
print("页面加载失败...")
return None
pattern = re.compile('<div class="article.*?alt="(.*?)".*?'+
'<div class="content">.*?span>(.*?)'+
'</span>.*?<i.*?<i class="number">(.*?)</i>.*?' +
'<i.*?>(.*?)</i>',re.S)
items = re.findall(pattern,page_code)
# 用来存储每页的段子们
page_stories = []
# 遍历正则表达式匹配的信息
replaceBR = re.compile('<br/>')
for item in items:
# 用换行替换掉内容中的<br/>,提升用户体验
text = re.sub(replaceBR,"\n",item[1])
# item[0]是用户名,item[1]是内容,item[2]是好笑数,item[3]是评论数
page_stories.append([item[0].strip(),text.strip(),
item[2].strip(),item[3].strip()])
return page_stories
# 加载并提取页面的内容,加入到列表中
def load_page(self):
# 如果当前未看的页数少于2页,则加载新的一页
if self.enable == True:
if len(self.stories) < 2:
# 获取新的一页
page_stories = self.get_page_items(self.page_index)
# 将该页的段子存放到全局list中
if page_stories:
self.stories.append(page_stories)
# 获取完之后页码索引加一,表示下次读取下一页
self.page_index += 1
# 调用该方法,每次敲回车打印输出一个段子
def get_one_story(self,page_stories,page):
# 遍历一页的段子
for story in page_stories:
# 等待用户输入
user_input = input().lower()
# 每当输入回车一次,判断是否加载新页面
# 如果输入Q,则程序结束
if user_input == "q":
self.enable = False
return None
self.load_page()
print("第%d页\t发布人:%s\t好笑:%s\t评论:%s\n%s" %
(page,story[0],story[2],story[3],story[1]))
# 开始方法
def start(self):
print("正在读取糗事百科,请按回车查看新段子,'Q'or'q'退出")
# 使变量为True,程序可以正常运行
self.enable = True
# 先加载一页内容
self.load_page()
# 局部变量,控制当前读到了第几页
now_page = 0
while self.enable:
if len(self.stories) > 0:
# 从全局list中获取一页的段子
page_stories = self.stories[0]
# 当前读到的页数加一
now_page += 1
# 将全局list中的第一个元素删除,因为已经取出
del self.stories[0]
# 输出该页的段子
self.get_one_story(page_stories,now_page)
if __name__ == "__main__":
spider = QSBK()
spider.start()