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

##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('\n')
        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('\n')
            print(f'正在采集"{m_title}"参赛人员信息..')
            self.parse_user()  # 调用解析参赛人员的数据

        for x in range(2, pages):  # 已知全部赛事的总页数为pages 开始下一页的采集
            print('☀'*30)
            print(f'正在采集第{x}页..')
            print('\n')
            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('\n')
            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('\n')
        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了(手动狗头)~~
##这个网站的bug还是挺明显,已经向管理员提交issue~

#end()

发布了12 篇原创文章 · 获赞 22 · 访问量 3246

猜你喜欢

转载自blog.csdn.net/bosslay/article/details/88750973