# 正则
import re
# 爬取网络数据
from urllib import request, parse
# 引入时间模块
import time
# 引入自己定义的工具类
# Tools用来清洗数据
# DBManger用来连接、关闭数据库并向数据库中插入数据
# 注:tools文件会在此博文下边给出
from tools import Tools, DBManger
声明爬虫类,定义初始化函数
class QSBKSpider(object):
def __init__(self):
self.url = 'https://www.qiushibaike.com/text/page/1'
self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0'}
self.html = ''
获取网页的函数
def get_html(self):
# 声明变量记录获取网页的次数
count = 1
# 循环 在此循环里爬取网页,当获取网页失败且获取此数小于10时,继续爬取
while 1:
# 判断网页获取是否成功
try:
req = request.Request(self.url, headers=self.headers)
response = request.urlopen(req)
self.html = response.read().decode('utf-8')
# 不成功的话先判断获取此网页的此数,如果大于10,则退出;如果小于10次,则继续爬取
except Exception as e:
count += 1
if count>10:
print('当前页数据获取失败!')
break
print('{},正在尝试第{}次连接'.format(e,count))
# 成功爬取到网页则跳出循环
else:
break
# 设置每爬取一次 间歇一分钟
time.sleep(1)
解析数据 获取下一页链接
此处的难点与重点是获取下一页链接的方法
# 解析数据
def parse_data(self):
# 准备正则
pattern = re.compile('<div.*?class="author.*?<h2>(.*?)</h2>.*?<div class="articleGender.*?>(.*?)</div>.*?<div '
'class="content.*?<span>(.*?)</span>.*?<i class="number.*?>(.*?)</i.*?<i.*?>(.*?)</i>',
re.S)
res = re.findall(pattern, self.html)
for info in res:
msg = list(info)
# 清洗数据
msg[0] = Tools.strip_char(info[0])
msg[2] = Tools.strip_char(info[2])
# print('用户昵称:{}\n年龄:{}\n 内容:{}\n 好笑数:{}\n 评论数:{}'.format(msg[0],msg[1],msg[2],msg[3],msg[4]))
# 将处理之后的数据填入数据库中 在此传递的参数可以是元组也可以是列表
DBManger.insert_data(msg)
# 正则直接找不到下一页链接,需要先找class="next"的位置
# find()函数如果找到就返回字符串在网页中的位置,没有找到返回-1
index = self.html.find('class="next"')
# 如果找到class="next"
if index != -1:
# 截取它前一部分的字符串,这部分字符串将链接包括着
s = self.html[index-100:index]
# 再使用正则从截取的字符串中进行匹配
next_pat = re.compile('href="(.*?)"')
next_href = re.search(next_pat, s)
page = next_href.group(1).split('/')[-2]
print('正在爬取第{}页'.format(page))
self.url = 'https://www.qiushibaike.com' + next_href.group(1)
self.get_html()
# 调用自身函数 解析数据
self.parse_data()
else:
print('没有下一页...')
启动爬虫的函数
def start(self):
self.get_html()
self.parse_data()
if __name__ == '__main__':
# 先连接数据库
DBManger.connect_db()
# 爬虫
qsbk = QSBKSpider()
qsbk.start()
# 关闭数据库
DBManger.close_db()
附:文件tools,此文件包含两个工具类
# -*- coding:utf-8 -*-
import re
import sqlite3
class Tools(object):
@classmethod
def strip_char(cls,string):
"""
:param string: 要进行处理的数据
:return: 处理之后的数据
"""
# 利用正则去除字符
string = re.sub(re.compile('\n|\t| ', re.S), '', string)
# 将换行标签替换为\n
string = re.sub(re.compile('</br/>'),'\n',string)
return string
# 数据库的管理类
class DBManger(object):
# 声明类变量
connect = None
cursor = None
# 连接数据库的操作
@classmethod
def connect_db(cls):
cls.connect = sqlite3.connect('qsbk.db')
cls.cursor = cls.connect.cursor()
# 关闭数据库的操作
@classmethod
def close_db(cls):
cls.cursor.close()
cls.connect.close()
# 向数据库中插入数据
@classmethod
def insert_data(cls,dz_tuple):
sql = 'INSERT INTO qsbk(name,age,content,vote,comments)VALUES ("%s",%s,"%s",%s,%s)'%(dz_tuple[0],dz_tuple[1],dz_tuple[2],dz_tuple[3],dz_tuple[4])
# 执行SQL语句
cls.cursor.execute(sql)
cls.connect.commit()
DBManger.connect_db()