多进程课程数据爬取存放MySql数据库20210512

多进程课程数据爬取存放MySql数据库

需求描述:

爬取网易云课堂课程信息,并使用PyMySql模块将数据保存到MySQL数据库中。
核心技术:PyMySQL模块操作数据库,multiprocessing模块可以实现多进程。本例使用Pool进程池的方式来实现多进程的功能

前期准备:

创建数据库

utf-8

CREATE DATABASE pydb DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

创建课程数据表

-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course_pro`;
CREATE TABLE `course_pro` (
  `course_id` bigint(20) NOT NULL COMMENT '课程id',
  `product_id` bigint(20) NOT NULL COMMENT '产品id',
  `product_type` int(11) NOT NULL COMMENT '产品类型',
  `product_name` varchar(125) NOT NULL COMMENT '产品名称',
  `provider` varchar(125) NOT NULL COMMENT '厂家',
  `score` float DEFAULT NULL COMMENT '分数',
  `score_level` int(11) DEFAULT NULL COMMENT '分数等级',
  `learner_count` int(11) DEFAULT NULL COMMENT '学习者数量',
  `lesson_count` int(11) DEFAULT NULL COMMENT '课程数量',
  `lector_name` varchar(125) DEFAULT NULL COMMENT '读者名',
  `original_price` float DEFAULT NULL,
  `discount_price` float DEFAULT NULL COMMENT '折扣价格',
  `discount_rate` float DEFAULT NULL COMMENT '折扣比例',
  `img_url` varchar(125) DEFAULT NULL COMMENT '图片url地址',
  `big_img_url` varchar(255) DEFAULT NULL COMMENT '大图url地址',
  `description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci COMMENT '描述',
  PRIMARY KEY (`course_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

安装 pymysql

pip install pymysql -i 

清华大学	https://pypi.tuna.tsinghua.edu.cn/simple
阿里云	http://mirrors.aliyun.com/pypi/simple/
中国科技大学	https://pypi.mirrors.ustc.edu.cn/simple/
华中理工大学	http://pypi.hustunique.com/
山东理工大学	http://pypi.sdutlinux.org/
豆瓣	http://pypi.douban.com/simple/

python代码实现


import requests
import time
import pymysql

from multiprocessing import Pool

conn = pymysql.connect(
    host='192.168.10.102',
    port=3306,
    user='root',
    passwd='mysql123',
    db='pydb',
    charset='utf8'
)  # 连接数据库

cur = conn.cursor()


def get_json(index):
    '''
    爬取课程的JSON数据

    :param index: 当前索引,从0开始
    :return: JSON数据
    '''
    # 此url的获取是登录https://study.163.com/
    # 点击网易network
    # 点击搜索python查看network中的json
    url = 'https://study.163.com/p/search/studycourse.json'

    payload = {
        'activityId': 0,
        'keyword': "python",
        'orderType': 50,
        # 'pageIndex': 1,
        'pageIndex': index + 1,
        'pageSize': 50,
        'priceType': -1,
        'qualityType': 0,
        'relativeOffset': 0,
        'searchTimeType': -1,
    }

    headers = {
        'authority': 'study.163.com',
        'accept': 'application/json',
        'accept-encoding': 'gzip, deflate, br',
        'content-type': 'application/json',
        'origin': 'https://study.163.com',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3868.400 QQBrowser/10.8.4394.400'
    }

    try:
        # 发送POST请求
        response = requests.post(url, json=payload, headers=headers)
        # 获取JSON数据
        content_json = response.json()
        if content_json and content_json['code'] == 0:
            return content_json
        return None
    except Exception as e:
        print('出错,请核实后重试!')
        print(e)
        return None


def get_content(content_json):
    '''
    获取课程信息列表
    :param content_json: 获取的JSON格式数据
    :return: 课程数据
    '''
    if 'result' in content_json:
        return content_json['result']['list']


def check_course_exit(course_id):
    '''
    检查课程是否存在:
    :param couse_id: 课程ID
    :return: 课程存在返回True,否则返回False
    '''
    print(f'check_course_exit {course_id}')
    sql = f'select course_id from course where course_id = {course_id}'
    print(f'check_course_exit: {sql}')
    cur.execute(sql)
    course = cur.fetchone()
    if course:
        return True
    else:
        return False


def save_to_course(course_data):
    # sql_course = '''insert into course(`course_id`,`product_id`,`product_type`,`product_name`,`provider`,`score` ,`learner_count`,`lesson_count` ,`lector_name` ,`original_price` ,`discount_price`,`discount_rate`,`img_url`,`big_img_url`,`description`) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) '''
    sql_course = '''insert into course values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) '''

    print('save_to_course')
    print(sql_course)
    print(course_data)
    #executemany插入多条记录
    cur.executemany(sql_course, course_data)


def save_mysql(content):
    course_data = []
    # Column count doesn't match value count at row 1
    # 列不匹配
    try:

        for item in content:
            print(item)
            #如果数据库没有该条数据则保留
            if not check_course_exit(item['courseId']):
                #加入元组中
                course_value = \
                    (item['courseId'], item['productId'], item['productType'], item['productName'],
                     item['provider'], item['score'], item['scoreLevel'], item['learnerCount'],
                     item['lessonCount'], item['lectorName'], item['originalPrice'], item['discountPrice'],
                     item['discountRate'], item['imgUrl'], item['bigImgUrl'], item['description']
                     )
                print('course_value:', course_value)
                course_data.append(course_value)
        save_to_course(course_data)
    except Exception as ex:
        print('save_mysql', ex)


def main(index):
    #获取JSON格式数据
    content_json = get_json(index)
    #获取课程内容
    content = get_content(content_json)
    #保存到数据库
    save_mysql(content)
    conn.commit() # 提交到数据库


if __name__ == '__main__':
    print('开始执行')
    start = time.time()
    #获取总页数
    totlePageCount = get_json(1)['result']['query']['totlePageCount']  # 获取总页数
    print('totlePageCount', totlePageCount)
    # if totlePageCount > 0:
    #     for i in range(totlePageCount):
    #         main(i + 1)
    #使用多进程
    pool = Pool()
    #生成当前页码元组
    index = ([x for x in range(totlePageCount)])
    #执行多进程
    pool.map(main,index) #执行多进程
    pool.close() #关闭进程
    pool.join()#等待子进程结束


    cur.close() #关闭游标
    #conn.commit() # 提交到数据库
    conn.close() # 关闭数据库连接
    print('执行结束')
    end = time.time()
    print(f'程序执行时间是{end - start}秒.')

# 程序执行时间是3.5287063121795654秒.
# 耗时3.5秒中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Narutolxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值