博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python每日一练(11)-爬取在线课程
阅读量:112 次
发布时间:2019-02-26

本文共 17345 字,大约阅读时间需要 57 分钟。

目录

1. 爬取在线课程Excel版

昨天呢笔者外出去吃了一顿火锅,疫情期间在家馋了好久勒,所以就没有更新Python的每日一练,今天中午吃了饭之后,赶紧打开电脑给补上,嘿嘿。今天的案例主要是去爬取网易云课堂上与Python相关的1200多门课程。如图所示。

在这里插入图片描述如果我们要在网易云上发布一门Python课程,那么就要对竞品进行分析。而要对竞品分析,首先要获取竞品数据,那么使用爬虫技术再合适不过了。使用Python爬虫技术爬取网易云课堂全部Python课程数据,并将爬取到的课程信息数据写入到Excel表格中。这个案例的技术要点就是将数据输入存入Excel,我们使用xlsxwriter模块实现该功能。使用前一定要安装该模块:

pip install --user  -i http://pypi.douban.com/simple --trusted-host pypi.douban.com xlsxwriter

效果如图所示:

在这里插入图片描述
使用xlsxwriter模块基本步骤及流程如下所示:

import xlsxwriter  # 1.导入# 2.创建Excel文件 参数为: Excel名称work_book = xlsxwriter.Workbook("网易云课堂Python课程数据.xlsx")# 3.创建sheetwork_sheet = work_book.add_worksheet("Sheet1")# 4.写入数据# 第一个参数表示行(从0开始) 第二个参数表示列(从0开始) 第三个参数是该表格的内容work_sheet.write(0, 0, "商品ID")work_sheet.write(0, 1, "课程ID")work_sheet.write(0, 2, "商品名称")work_sheet.write(0, 3, "商品类型")work_sheet.write(0, 4, "机构名称")work_sheet.write(0, 5, "评分")# 5.关闭excel写入work_book.close()

运行程序,使用xlsxwriter模块生成的Excel表格如图所示。

在这里插入图片描述
先来分析一下网易云课堂Python课程页面。在百度搜索框中输入网易云课堂访问网易云课堂首页,在首页搜索栏中输入Python关键字,进入Python课程页面,然后单击全部选项,显示全部Python课程,如下图所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进入到上面的页面之后,在网页上任意一个空白地方单击鼠标右键,选择检查。调出了控制台之后,然后点击Network,在按F5或者是浏览器左上角刷新页面。如图所示。
在这里插入图片描述
在这里插入图片描述
我们发现课程信息没有直接显示页面中,而是保存在studycourse.json文件中,如图所示。
在这里插入图片描述
通过以上分析,下面我们就可以使用requests模块来获取课程数据信息,使用xlsxwriter模块将课程信息写入到Excel表格。具体步骤如下:
1.由于使用了第三方模块requestsxlsxwriter,所以需要先安装该模块。已经安装过的可以不用再安装。使用pip命令如下:

pip install --user  -i http://pypi.douban.com/simple --trusted-host pypi.douban.com requestspip install --user  -i http://pypi.douban.com/simple --trusted-host pypi.douban.com xlsxwriter

2.导入程序中需要使用的模块,具体代码如下:

import requestsimport xlsxwriter

3.首先使用requests模块发送POST请求, 获取到当前页数的课程信息,然后使用json()方法获取到Json格式数据,接下来使用xlsxwriter模块将获取到的当前页数的信息写入到Excel。最后在依次遍历每一页的课程信息。代码如下:

import requestsimport xlsxwriter  # 导入def get_json(index):    """    爬取课程的json数据    :param index: 页码 pageIndex 从1开始    :return: json数据    """    url = "https://study.163.com/p/search/studycourse.json"    payload = {
"pageSize": 50, "pageIndex": index, "relativeOffset": 0, "searchTimeType": -1, "orderType": 5, "priceType": -1, "activityId": 0, "qualityType": 0, "keyword": "python" } # 请求体 headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" " (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36", "accept": "application/json", "content-type": "application/json", "origin": "https://study.163.com" } # 请求头 response = requests.post(url, json=payload, headers=headers) if response.status_code == 200: # 根据状态码判断是否请求成功 content_json = response.json() # 获取json数据 if content_json and content_json["message"] == "ok": # 判断数据是否存在 return content_json else: print("请求数据失败~") return Nonedef get_content(content_json): """ 获取课程信息列表 :param content_json: 通过get_json函数获取的json格式数据 :return: 课程数据 """ if "result" in content_json: return content_json["result"]["list"] # 返回课程数据列表def save_excel(content, index): """ 存储到Excel :param content: 课程内容 :param index: 索引值,从0开始 :return: None """ for num, item in enumerate(content): # 因为Excel第一行要写入标题 所以row从1开始 row = 50 * (index - 1) + (num + 1) # 行内容 work_sheet.write(row, 0, str(item["productId"])) work_sheet.write(row, 1, str(item["courseId"])) # 以文本的形式在Excel单元格中显示 work_sheet.write(row, 2, item["productName"]) work_sheet.write(row, 3, item["productType"]) work_sheet.write(row, 4, item["provider"]) work_sheet.write(row, 5, item["score"]) work_sheet.write(row, 6, item["scoreLevel"]) work_sheet.write(row, 7, item["learnerCount"]) work_sheet.write(row, 8, item["lessonCount"]) work_sheet.write(row, 9, item["lectorName"]) work_sheet.write(row, 10, item["originalPrice"]) work_sheet.write(row, 11, item["discountPrice"]) work_sheet.write(row, 12, item["discountRate"]) work_sheet.write(row, 13, item["imgUrl"]) work_sheet.write(row, 14, item["bigImgUrl"]) work_sheet.write(row, 15, item["description"])def main(index): """ 主函数 :param index: 索引值,从1开始 :return: """ content_json = get_json(index) # 取出json数据 content = get_content(content_json) # 取出课程信息 save_excel(content, index) # 存入Excelif __name__ == '__main__': # 程序入口 print("*******************开始执行*******************") work_book = xlsxwriter.Workbook("网易云课堂Python课程数据.xlsx") # 创建excel文件 work_sheet = work_book.add_worksheet("first_sheet") # 创建sheet # 行首标题 work_sheet.write(0, 0, "商品id") work_sheet.write(0, 1, "课程id") work_sheet.write(0, 2, "课程名称") work_sheet.write(0, 3, "课程类型") work_sheet.write(0, 4, "机构名称") work_sheet.write(0, 5, "评分") work_sheet.write(0, 6, "评分等级") work_sheet.write(0, 7, "学习人数") work_sheet.write(0, 8, "课程节数") work_sheet.write(0, 9, "讲师名称") work_sheet.write(0, 10, "原价") work_sheet.write(0, 11, "折扣价") work_sheet.write(0, 12, "折扣率") work_sheet.write(0, 13, "课程小图url") work_sheet.write(0, 14, "课程大图url") work_sheet.write(0, 15, "课程描述") total_page_count = get_json(1)["result"]["query"]["totlePageCount"] for i in range(total_page_count): main(i + 1) # i+1即为页码 work_book.close() # 关闭excel写入 print("*******************执行结束*******************")

运行程序会生成一个Excel表格,如图所示。

在这里插入图片描述

2. 爬取在线课程MySQL版

对于使用爬虫爬取到的数据,通常将其保存到文件或是数据库中。这次将使用requests模块爬取网易云课程,并使用pymysql模块将爬取到的数据存入到MySQL数据库中。爬取后效果如图所示。

在这里插入图片描述
Python中操作mysql步骤:
在这里插入图片描述
(1) 安装第三方模块pymysql,命令如下:

pip install pymysql

(2) 在py文件中引入pymysql模块

from pymysql import *

(3) 建立连接

# 1.建立数据库链接# host: 连接的mysql主机 本机写'localhost'# port: 连接的mysql主机端口 默认是3306# database: 数据库的名称# user: 连接的用户名# password: 连接的密码# charset: 通信采用的编码方式,推荐使用utf8conn = connect(host="localhost", port=3306, database="wyy_spider", user="root", password="mysql", charset="utf8")# 对象的方法如下:# close()关闭连接# commit()提交# cursor() 返回Cursor对象,用于执行sql语句并获得结果

(4) 创建cursor对象

# 用于执行sql语句 使用频度最高的语句为select、insert、update、delete# 获取Cursor对象: 调用Connection对象的cursor()方法cs1 = conn.cursor()# close()关闭# execute(operation [, parameters ])执行语句,返回受影响的行数,主要用于执行insert、update、delete语句,也可以执行create、alter、drop等语句# fetchone()执行查询语句时,获取查询结果集的第一个行数据,返回一个元组# fetchall()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回

2.1 增删改查

向数据库中添加数据,示例代码如下:

from pymysql import *  # 导入if __name__ == '__main__':    # 1.建立连接    conn = connect(host="localhost", port=3306, database="wyy_spider",                   user="root", password="mysql", charset="utf8")    # 2.创建cursor对象    cs1 = conn.cursor()    # 3.操作数据    # 3.1 插入一条数据    count = cs1.execute("insert into teacher(name,age) values('Amo',18)")    print(count)  # 打印受影响的行数    count = cs1.execute("insert into teacher(name,age) values('zy',16)")    print(count)  # 打印受影响的行数    sql = "insert into teacher(name,age) values(%s, %s)"    # 第一个参数: 固定的sql语法    # 第二个参数: 列表 列表里面的元素是由一个一个的元组组成    cs1.executemany(sql, [("Jerry", 35), ("Paul", 21), ("Jason", 26)])    # 3.2 插入多条数据    # 提交之前的操作    conn.commit()    # 关闭Cursor对象和Connection对象    cs1.close()    conn.close()

在这里插入图片描述

从数据库中删除数据,示例代码如下:

from pymysql import *  # 导入if __name__ == '__main__':    # 1.建立连接    conn = connect(host="localhost", port=3306, database="wyy_spider",                   user="root", password="mysql", charset="utf8")    # 2.创建cursor对象    cs1 = conn.cursor()    # 3.操作数据    count = cs1.execute("delete from teacher where name='Jerry'")    print(count)    # 提交之前的操作    conn.commit()    # 关闭Cursor对象和Connection对象    cs1.close()    conn.close()

在这里插入图片描述

更改数据库中的部分数据,示例代码如下:

from pymysql import *  # 导入if __name__ == '__main__':    # 1.建立连接    conn = connect(host="localhost", port=3306, database="wyy_spider",                   user="root", password="mysql", charset="utf8")    # 2.创建cursor对象    cs1 = conn.cursor()    # 3.操作数据    count = cs1.execute("update teacher set age=18 where name='zy'")    print(count)    # 提交之前的操作    conn.commit()    # 关闭Cursor对象和Connection对象    cs1.close()    conn.close()

在这里插入图片描述

查询数据库中的数据,示例代码如下:

from pymysql import *  # 导入if __name__ == '__main__':    # 1.建立连接    conn = connect(host="localhost", port=3306, database="wyy_spider",                   user="root", password="mysql", charset="utf8")    # 2.创建cursor对象    cs1 = conn.cursor()    # 3.操作数据    count = cs1.execute("select * from teacher where age > 18")    print(count)    # for i in range(count):    #     # 获取查询的结果    #     result = cs1.fetchone()    #     print(result)  # 打印结果 返回结果为一个元组 ('Paul', 21)    result = cs1.fetchall()    # (('Paul', 21), ('Jason', 26))    print(result)  # 返回的结果是一个元组 元组的元素由元组组成    # 提交之前的操作    conn.commit()    # 关闭Cursor对象和Connection对象    cs1.close()    conn.close()

2.2 代码实现

实现将爬取信息写入数据库的功能,需要先创建数据库,创建数据表,然后编写代码实现该功能。具体步骤如下:

(1) 创建数据库。可以使用控制台或者MySQL可视化工具创建一个名为wyy_spider的数据库。如图所示:
在这里插入图片描述
(2) 创建数据表。通过如下SQL语句来创建course表:

create table course(	course_id bigint(20) not null,    product_id bigint(20) not null,    product_type int(11) not null,    product_name varchar(125) not null,    provider varchar(125) not null,    score float default null,    score_level int(11) default null,    learner_count int(11) default null,    lesson_count int(11) default null,    lector_name varchar(125) default null,    original_price float default null,    discount_price float default null,    discount_rate float default null,    img_url varchar(125) default null,    big_img_url varchar(125) default null,    description text,    primary key(course_id)) engine=InnoDB default charset=utf8;

(3) 最后代码如下:

# -*- coding: utf-8 -*-# @Time    : 2020/4/11 16:44# @Author  : 我就是任性-Amo# @FileName: 66.爬取在线课程.py# @Software: PyCharm# @Blog    :https://blog.csdn.net/xw1680from pymysql import *import requestsimport time  # 导入def get_json(index):    """    爬取课程的json数据    :param index: 页码 pageIndex 从1开始    :return: json数据    """    url = "https://study.163.com/p/search/studycourse.json"    payload = {
"pageSize": 50, "pageIndex": index, "relativeOffset": 0, "searchTimeType": -1, "orderType": 5, "priceType": -1, "activityId": 0, "qualityType": 0, "keyword": "python" } # 请求体 headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/" "537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36", "accept": "application/json", "content-type": "application/json", "origin": "https://study.163.com" } # 请求头 response = requests.post(url, json=payload, headers=headers) if response.status_code == 200: # 根据状态码判断是否请求成功 content_json = response.json() # 获取json数据 if content_json and content_json["message"] == "ok": # 判断数据是否存在 return content_json else: print("请求数据失败~") return Nonedef get_content(content_json): """ 获取课程信息列表 :param content_json: 通过get_json函数获取的json格式数据 :return: 课程数据 """ if "result" in content_json: return content_json["result"]["list"] # 返回课程数据列表def check_course_exit(course_id): """ 检查课程是否存在 :param course_id: 课程id :return: 课程存在返回True 否则返回False """ sql = f'select course_id from course where course_id = {course_id}' cs1.execute(sql) course = cs1.fetchone() if course: return True else: return Falsedef save_to_course(course_data): sql_course = """insert into course values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) """ cs1.executemany(sql_course, course_data)def save_mysql(content): course_data = [] for item in content: 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'],) course_data.append(course_value) save_to_course(course_data)def main(index): """ 主函数 :param index: 索引值,从1开始 :return: """ content_json = get_json(index) # 取出json数据 content = get_content(content_json) # 取出课程信息 save_mysql(content) # 存入数据库if __name__ == '__main__': # 程序入口 # 1.建立数据库链接 # host: 连接的mysql主机 本机写'localhost' # port: 连接的mysql主机端口 默认是3306 # database: 数据库的名称 # user: 连接的用户名 # password: 连接的密码 # charset: 通信采用的编码方式,推荐使用utf8 conn = connect(host="localhost", port=3306, database="wyy_spider", user="root", password="mysql", charset="utf8") # 2.创建cursor对象 # 用于执行sql语句 使用频度最高的语句为select、insert、update、delete # 获取Cursor对象: 调用Connection对象的cursor()方法 cs1 = conn.cursor() print("*******************开始执行*******************") start = time.time() total_page_count = get_json(1)['result']["query"]["totlePageCount"] # 获取总页数 for i in range(total_page_count): main(i + 1) conn.commit() cs1.close() conn.close() print("执行结束") end = time.time() print(f"程序执行时间是{end - start}秒") print("*******************执行结束*******************")

程序运行结果如图所示,并且数据已经插入到mysql数据库中:

在这里插入图片描述

3. 使用多进程爬取在线课程MySQL版

如果爬取的数据内容较多,存在多个分页,使用普通方式用时会较长。针对这种情况,可以使用多进程的方式来提高爬取数据和存入数据库的效率。如果大家对多任务不熟悉的话,可以去观看博主的另外一篇博客 。运行效果如图所示。

在这里插入图片描述
使用多任务爬取数据的时候,建议大家先将建表中的主键给去掉,先将数据爬取下来,然后再去数据库中去重。否则可能会出错,如下图所示。
在这里插入图片描述
示例代码如下:

from pymysql import *import requestsimport time  # 导入from multiprocessing import Pooldef get_json(index):    """    爬取课程的json数据    :param index: 页码 pageIndex 从1开始    :return: json数据    """    url = "https://study.163.com/p/search/studycourse.json"    payload = {
"pageSize": 50, "pageIndex": index, "relativeOffset": 0, "searchTimeType": -1, "orderType": 5, "priceType": -1, "activityId": 0, "qualityType": 0, "keyword": "python" } # 请求体 headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/" "537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36", "accept": "application/json", "content-type": "application/json", "origin": "https://study.163.com" } # 请求头 response = requests.post(url, json=payload, headers=headers) if response.status_code == 200: # 根据状态码判断是否请求成功 content_json = response.json() # 获取json数据 if content_json and content_json["message"] == "ok": # 判断数据是否存在 return content_json else: print("请求数据失败~") return Nonedef get_content(content_json): """ 获取课程信息列表 :param content_json: 通过get_json函数获取的json格式数据 :return: 课程数据 """ if "result" in content_json: return content_json["result"]["list"] # 返回课程数据列表def check_course_exit(course_id): """ 检查课程是否存在 :param course_id: 课程id :return: 课程存在返回True 否则返回False """ sql = f'select course_id from course where course_id = {course_id}' cs1.execute(sql) course = cs1.fetchone() if course: return True else: return Falsedef save_to_course(course_data): sql_course = """insert into course values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) """ cs1.executemany(sql_course, course_data)def save_mysql(content): course_data = [] for item in content: 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'],) course_data.append(course_value) save_to_course(course_data)def main(index): """ 主函数 :param index: 索引值,从1开始 :return: """ content_json = get_json(index) # 取出json数据 content = get_content(content_json) # 取出课程信息 save_mysql(content) # 存入数据库if __name__ == '__main__': # 程序入口 # 1.建立数据库链接 # host: 连接的mysql主机 本机写'localhost' # port: 连接的mysql主机端口 默认是3306 # database: 数据库的名称 # user: 连接的用户名 # password: 连接的密码 # charset: 通信采用的编码方式,推荐使用utf8 conn = connect(host="localhost", port=3306, database="wyy_spider", user="root", password="mysql", charset="utf8") # 2.创建cursor对象 # 用于执行sql语句 使用频度最高的语句为select、insert、update、delete # 获取Cursor对象: 调用Connection对象的cursor()方法 cs1 = conn.cursor() print("*******************开始执行*******************") start = time.time() total_page_count = get_json(1)['result']["query"]["totlePageCount"] # 获取总页数 # for i in range(total_page_count): # main(i + 1) 不使用多任务的方式 pool = Pool() index_list = [i for i in range(total_page_count)] # map(self, func, iterable, chunksize=None): pool.map(main, index_list) # 执行多任务 pool.close() # 关闭进程池 pool.join() # 等待子进程结束 conn.commit() cs1.close() conn.close() print("执行结束") end = time.time() print(f"程序执行时间是{end - start}秒") print("*******************执行结束*******************")

运行结果如图所示:

在这里插入图片描述
从运行结果可以看出,比之前的执行时间短了很多。至此今天的案例就到此结束了,另外笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习Python基础的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。编写不易,请大家手留余香~。

你可能感兴趣的文章