本文共 17345 字,大约阅读时间需要 57 分钟。
昨天呢笔者外出去吃了一顿火锅,疫情期间在家馋了好久勒,所以就没有更新Python的每日一练,今天中午吃了饭之后,赶紧打开电脑给补上,嘿嘿。今天的案例主要是去爬取网易云课堂上与Python相关的1200多门
课程。如图所示。
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课程
,如下图所示。 鼠标右键
,选择检查
。调出了控制台之后,然后点击Network
,在按F5
或者是浏览器左上角
刷新页面。如图所示。 studycourse.json
文件中,如图所示。 requests模块
来获取课程数据信息,使用xlsxwriter模块
将课程信息写入到Excel表格。具体步骤如下: 1.由于使用了第三方模块requests
和xlsxwriter
,所以需要先安装该模块。已经安装过的可以不用再安装。使用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表格,如图所示。
对于使用爬虫爬取到的数据,通常将其保存到文件或是数据库中。这次将使用requests
模块爬取网易云课程,并使用pymysql模块
将爬取到的数据存入到MySQL数据库
中。爬取后效果如图所示。
mysql
步骤: 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()执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回
向数据库中添加数据,示例代码如下:
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()
实现将爬取信息写入数据库的功能,需要先创建数据库,创建数据表,然后编写代码实现该功能。具体步骤如下:
(1) 创建数据库。可以使用控制台
或者MySQL可视化工具
创建一个名为wyy_spider
的数据库。如图所示: 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
数据库中:
如果爬取的数据内容较多,存在多个分页,使用普通方式用时会较长。针对这种情况,可以使用多进程的方式来提高爬取数据和存入数据库的效率。如果大家对多任务不熟悉的话,可以去观看博主的另外一篇博客 。运行效果如图所示。
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基础
的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。编写不易,请大家手留余香~。