Python入门级爬虫:某电竞赛事网站(JS加载)数据模型+Sqlite3数据库练习

2019-04-14 15:42发布

class="markdown_views prism-github-gist"> ##python小白,家庭作业一篇,本篇仅适合新手练习,大牛勿喷,欢迎交流~ import requests # 调用申请模块 import json # 调用json数据模块 import sqlite3 # 引入数据库 from func_items import Esport_Sql, Esport_User # 从功能模块调用电竞圈数据库函数 class E_Sport(object): '''一个电竞圈的数据模型''' def __init__(self): '''定义数据模型的基本属性''' self.url = 'http://api2.dianjingquan.cn:3004/match/query/list?page=1&page_count=40&key=&status=all&game_id=0'#初始网址 self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' }#请求头 self.create_table()#调用静态函数,创建数据库表 self.document = ''#定义获取到的网页源码转换后的json格式数据,初始值为空 self.response = '' #定义返回的网页源代码数据,初始值为空 self.error_count = 0 #定义错误次数初始值为0 @staticmethod # 静态函数装饰器 def create_table(): '''创建数据库表的静态函数''' database = sqlite3.connect('E_Sport.db') # 连接数据库 cursor = database.cursor() # 启动游标 sql_01 = "CREATE TABLE IF NOT EXISTS E_Sport_Match(m_id INTEGER PRIMARY KEY,m_title VARCHAR (20),m_name VARCHAR (10),m_date VARCHAR (30),m_reward VARCHAR (10),game_rules TEXT,details TEXT,m_max_count VARCHAR (10),m_count VARCHAR (10),m_img CHAR,m_url CHAR )" # 创建数据表,存放赛事信息 cursor.execute(sql_01)#执行sql语句 sql_02 = "CREATE TABLE IF NOT EXISTS E_Sport_User(user_id INTEGER PRIMARY KEY ,user_name VARCHAR (10),add_time VARCHAR (20),mobile VARCHAR (20))" # 创建数据表,存放玩家信息 cursor.execute(sql_02) # 执行sql语句 cursor.close() # 关闭游标 database.close() # 关闭数据库 def get_html(self, is_list=True): '''采集函数 发请求 拿数据''' try: # 调用异常捕获,以防程序报错 response = requests.get(self.url, headers=self.headers) # 发请求 拿回数据 self.response = response.text #text文本 print('-' * 30) except Exception as error: # 异常捕获,如果程序出错,会走这里的代码 self.error_count += 1 # 每次出错,错误次数+1 if self.error_count > 3: # 此处加以判断,如果出错次大于3 print('重连次数过多,将跳过此条..') # 程序提前结束 return self.get_html(is_list=is_list) # 若出错次数在3之内,继续调用采集函数,直到成功返回数据or提前结束 else: self.error_count = 0 # 三次之内成功,错误次数归 0 if is_list: # 判断参数布尔值是否为真 self.parse_html() # 为True才会调用起始页解析函数 def parse_html(self): '''解析函数:解析起始页的数据''' self.document = json.loads(self.response) # 将返回的数据转换成json格式 pages = self.document.get('pages') # 获取全部赛事的总页数 total_matches = self.document.get('total') # 获取全部赛事的数量 matches = self.document.get('matchs') # 获取当前页赛事的信息,得到一个列表,包含四十个字典数据 print('正在采集起始页数据.') print(' ') for match in matches: # 迭代这个列表,准备解析数据 m_id = match.get('id') # 获取赛事id,根据这个id,可以在之后的详情页请求中拿回更多的数据 m_title = match.get('name') # 获取赛事标题 m_name = match.get('game_name') # 获取游戏名称 m_img = match.get('banner_url') # 获取赛事宣传图片地址 m_date = match.get('create_time') # 获取赛事创立时间 m_max_count = match.get('max_enroll_count') # 获取赛事报名人数限制 m_count = match.get('enroll_count') # 获取已报名人数数量 m_reward = match.get('total_reward') # 获取赛事奖金金额 self.url = f'http://api2.dianjingquan.cn:3004/match/base?match_id={m_id}&uid=0&access_token=' #通过赛事id拼接一个完整的赛事主办方详情页网址 self.get_html(is_list=False) # 此处调用采集函数对赛事主办方详情页进行采集时,传递的布尔值函数为False,故采集函数不会调用解析起始页的函数 print(f'正在采集"{m_title}"主办方信息..') self.parse_host(m_id, m_title, m_name, m_date, m_max_count, m_count, m_reward, m_img) # 调用解析函数对赛事主办方详情页进行解析,并且将已获得的部分数据传给解析函数,以便保存 self.url = f'http://api2.dianjingquan.cn:3004/match/user/list?match_id={m_id}&uid=0&access_token=' # 通过赛事id拼接一个完整的参赛人员详情页地址 self.get_html(is_list=False) # 此处调用采集函数对参赛人员详情页进行采集时,传递的布尔值函数为False,故采集函数不会调用解析起始页的函数 print(' ') print(f'正在采集"{m_title}"参赛人员信息..') self.parse_user() # 调用解析参赛人员的数据 for x in range(2, pages): # 已知全部赛事的总页数为pages 开始下一页的采集 print('☀'*30) print(f'正在采集第{x}页..') print(' ') self.url = f'http://api2.dianjingquan.cn:3004/match/query/list?page={x}&page_count=40&key=&status=all&game_id=0'#拼接下一页的地址 self.get_html()#调用采集函数,对下一页网址发起请求 def parse_user(self): '''解析函数:解析参赛人员详情页的数据''' self.document = json.loads(self.response) # 将返回的数据转化成json格式,为字典数据 user_lists = self.document.get('enroll_list') # 提取报名参赛人员详细信息,得到一个列表嵌套字典的数据 for user_list in user_lists: # 迭代这个列表 user_id = user_list.get('id') # 提取玩家id user_name = user_list.get('id_name') # 提取参赛玩家昵称 mobile = user_list.get('mobile') # 提取玩家手机号 add_time = user_list.get('add_time') # 获取玩家提交时间 print('正在写入数据库..') print(' ') user = Esport_User(user_id, user_name, add_time, mobile) # 创建一个Esport_User的模型对象,并将参数传入 user.save() # 调用Esport_User的保存数据函数 def parse_host(self, m_id, m_title, m_name, m_date, m_max_count, m_count, m_reward, m_img): '''解析函数:解析赛事主办方详情页的数据''' self.document = json.loads(self.response) # 将返回的数据转换为json格式 try: # 根据报错得知,有的数据里没有赛事规则,故调用异常捕获 game_rules = self.document.get('custom_property_list')[0].get('content') # 获取赛事规则 except Exception as e: game_rules = '规则缺失' infos = self.document.get('contact_list') # 获取主办方联系方式,得到一个列表嵌套三个字典的数据 details = '' # 主办方联系方式有好几种,先定义一个空字符串,后面往里填 for info in infos: # 迭代这个列表 type = info.get('type') # 获取主办方联系方式的具体信息 value = info.get('value') details += type + ':' + value + '|' # 将每次循环得到的结果用特定符号连接,然后填进字符串里 esport = Esport_Sql(m_id, m_title, m_name, m_date, m_reward, game_rules, details, m_max_count, m_count, m_img, self.url) ##建立一个ESport_Sql的对象 print(' ') print('正在写入数据库..') esport.save() # 调用ESport_Sql的赛事保存数据函数 def run(self): '''程序启动函数''' print('❀'*50) print('✲'*30) print('*'*20) print('*'*10) print('启动程序') self.get_html() if __name__ == '__main__':#在当前类调用 sport = E_Sport()#创建一个电竞圈模型的实例 sport.run()#启动函数

数据库代码封装,如下

import sqlite3#引入数据库 class Esport_Sql(): '''电竞圈爬取数据保存数据模型''' def __init__(self,m_id,m_title,m_name,m_date,m_reward,game_rules,details,m_max_count,m_count,m_img,m_url): self.m_title = m_title self.m_id = m_id self.m_name =m_name self.m_date = m_date self.m_reward = m_reward self.game_rules = game_rules self.details = details self.m_max_count = m_max_count self.m_count = m_count self.m_img = m_img self.m_url = m_url def save(self): '''赛事保存数据函数''' database = sqlite3.connect('E_Sport.db') cursor = database.cursor() insert_sql = f"""INSERT INTO E_Sport_Match(m_id,m_title,m_name,m_date,m_reward,game_rules,details,m_max_count,m_count,m_img,m_url) VALUES ({self.m_id},'{self.m_title}','{self.m_name}','{self.m_date}','{self.m_reward}','{self.game_rules}',"{self.details}",'{self.m_max_count}','{self.m_count}','{self.m_img}','{self.m_url}')""" try:#因数据有可能会重复,故调用异常捕获 cursor.execute(insert_sql) database.commit() except Exception as error: print('该条数据已经存在!') cursor.close()#关闭游标 database.close()#关闭数据库 class Esport_User(): '''有关参赛玩家的数据模型''' def __init__(self,user_id,user_name,add_time,mobile): '''定义参赛玩家数据模型的初始属性''' self.user_id = user_id self.user_name = user_name self.add_time = add_time self.mobile = mobile def save(self): database = sqlite3.connect('E_Sport.db') cursor = database.cursor() insert_sql = f"INSERT INTO E_Sport_User(user_id,user_name,add_time,mobile) VALUES ({self.user_id}," f"'{self.user_name}','{self.add_time}','{self.mobile}') " try: # 因数据有可能会重复,故调用异常捕获 cursor.execute(insert_sql) database.commit() except Exception as error: print('该条数据已经存在!') cursor.close()#关闭游标 database.close()#关闭数据库

程序爬取界面

在这里插入图片描述

数据库界面

在这里插入图片描述
在这里插入图片描述
现在的任务就是找bug了(手动狗头)~~
#end()