项目的开始
Begaining
“出题目也太麻烦了,太难想了!”在指导学生完成比赛项目的时候,两个学生吐槽道。
此时,我突然想到如果学生有Scratch的诗词列表,那就可以实现随机出题,完美解决他们的这一问题,于是项目式自学的旅程开始!
Trip
计划
第一步:爬取诗句存储下来;
第二步:通过CodeLab的EIM扩展,让Scratch可以利用python获取数据。
对上述步骤进行了简单的可行性分析:
1.简单了解了下爬虫,发现正好有爬诗句的程序;
2.测试了下CodeLab的EIM使用方法,断定是可用的。
Trip
Python爬虫
CV大师|爬取诗词的程序
Ctr+C and Ctr+V
检索到了爬取诗词的程序:
python基础-古诗词填词游戏
https://blog.youkuaiyun.com/qq_42965915/article/details/108346932
该程序爬取的是中学阶段的诗词,我想要爬取的是小学诗词,于是修改了两处(8行及43行)代码后,便完成了爬取小学阶段的程序。
期间在朋友的提醒下,增加了time.sleep()(48行)防止自己被拉黑。
在读程序过程中,查询了下xpath方法以及如何查看xpath涉及的class名称。
了解到的查看方法放在文末附录处。
import requests
from lxml import etree
import time
class GetPoem:
def __init__(self):
self.url = 'https://so.gushiwen.cn/gushi/xiaoxue.aspx'#找到小学的链接复制过来
self.headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}
self.pl = dict()
def get_html(self):
try:
response = requests.get(url=self.url, headers=self.headers)
if response.status_code == 200:
return response.text
else:
print('页面获取错误:状态码{}'.format(response.status_code))
except Exception as e:
raise ConnectionError('获取网页失败!')
def parse(self):
response = self.get_html()
source = etree.HTML(response)
chapters = source.xpath('//div[@class="typecont"]')
# time.sleep(1)
return chapters
def get_poem_list(self):
for chapter in self.parse():
grade = chapter.xpath('./div/strong/text()')[0]
# print(grade)
titles = chapter.xpath('./span')
sector = list()
for title in titles:
head = title.xpath('./a/text()')[0]
# print(head)
poem_link = title.xpath('./a/@href')[0]
# print(poem_link)
poem = requests.get(poem_link)
page = etree.HTML(poem.text)
author = page.xpath('//p[@class="source"]/a[1]/text()')[0]#读取作者姓名为a[1],读取朝代为a[2]
content = [word.strip('\n') for word in page.xpath('//div[@class="left"]/div[@class="sons"]['
'1]/div[@class="cont"]/div['
'@class="contson"]//text()')]
sector.append({'title': head, 'author': author, 'content': content})
time.sleep(1)
self.pl.update({grade: sector})
Excel|数据的存储
Xlsxwriter案例迁移
上述爬取诗词的链接中,作者并没有做数据的存储工作,于是开始尝试存储。
因为自己之前有过用Python处理Excel数据的经验,于是找来一个Excel数据写入案例:
Python写入Excel文件-多种实现方式(测试成功,附代码)
https://blog.youkuaiyun.com/qq_44695727/article/details/109174842
参考案例中建表和写入的方法,编写好了数据存储在Excel的程序:
import getpoem
import xlsxwriter as xw
all_poem = getpoem.GetPoem()
get_poem = all_poem.get_poem_list()
poem_list = all_poem.pl
workbook = xw.Workbook('poem.xlsx') # 创建工作簿
worksheet1 = workbook.add_worksheet("sheet1") # 创建子表
worksheet1.activate() # 激活表
head = ['年级', '诗名', '作者', '内容'] # 设置表头
worksheet1.write_row('A1', head) # 从A1单元格开始写入表头
i = 2
for pl in poem_list.keys():
for poem in poem_list[pl]:
title = poem['title']
author = poem['author']
content = poem['content']
p = [pl, title, author]
worksheet1.write_row('A{}'.format(i), p)
worksheet1.write_row('D{}'.format(i), content)
i += 1
workbook.close() # 关闭表
REFLECTION
这次为了省事就选择了熟悉的Excel,下一次可以了解一下怎么用数据库来存储。
Excel|数据的筛选
Xlrd and Xlsxwriter
存储的初始数据
初始数据还存在很多问题:
1.诗句没有断开;
2.存在空白格。
本来想手动删除空白格再断开诗句,朋友看到后说我没有程序员的思维,作为程序员,能交给程序做的就给程序做,而且正好练手。
于是开始写程序来完成所有步骤:
a)空白格及特殊符号的移除
思路:挨个读取再挨个写入新的Excel,写入时跳过空白格,字符串内本身的首尾特殊符号可以用strip()删除。
def excel_strip(filename): # 将excel里面的空白格删掉,并且将字符串中的特殊字符删掉
new_book = xw.Workbook('poem_new.xlsx') # 创建工作簿
worksheet1 = new_book.add_worksheet("sheet1") # 创建子表
worksheet1.activate() # 激活表
workbook = xlrd.open_workbook(filename)
table = workbook.sheet_by_index(0)
r = table.get_rows()
row = 0
for i in r:
col = 0
for cell in i:
if cell.value and cell.value[0] != '(' and cell.value[0] != '"':
worksheet1.write_string(row, col, cell.value.strip()) # 首尾删特殊符号
col += 1
row += 1
new_book.close()
运行程序后的效果
b)将诗句断成句子
思路:句子的分隔符主要包括逗号、句号、感叹号、问号,挨个用split()断开。
def poem_split(filename): # 将excel里面的空白格删掉,并且将字符串中的特殊字符删掉
new_book = xw.Workbook('poem_new.xlsx') # 创建工作簿
worksheet1 = new_book.add_worksheet("sheet1") # 创建子表
worksheet1.activate() # 激活表
workbook = xlrd.open_workbook(filename)
table = workbook.sheet_by_index(0)
r = table.get_rows()
w_row = 0 # 写入的行序号
r_row = 0 # 读取的行序号
for i in r:
w_col = 0 # 写入的列序号
r_col = 0 # 读取的列序号
for cell in i:
if r_col > 2: # 从诗句内容的列开始拆分
cells = cell.value.split('!') # 分别以对应的符号,拆分成列表
worksheet1.write_row(w_row, w_col, cells) # 将列表插入表格
w_col += len(cells)
else:
worksheet1.write_string(w_row, w_col, cell.value)
w_col += 1
r_col += 1
w_row += 1
r_row += 1
new_book.close()
重复上述两个步骤3-4次后的结果
c)筛出绝句
注:这里专门查了下四句的古诗叫什么,不确定是不是称为四言,结果发现绝句指的是四句一首的诗歌,四言指的是全首或基本上是四字句写成的诗歌。——百度百科
思路:大部分诗句都是绝句,统一的句数会比较方便后续学生出题使用,于是写了一个函数来筛选出绝句,只要判断有第五句,则跳过该行,不进行写入
def choose_four(filename):
new_book = xw.Workbook('poem_new.xlsx') # 创建工作簿
worksheet1 = new_book.add_worksheet("sheet1") # 创建子表
worksheet1.activate() # 激活表
workbook = xlrd.open_workbook(filename)
table = workbook.sheet_by_index(0)
r = table.get_rows()
row = 0
for i in r:
col = 0
if not i.__getitem__(7).value:# 判断是否有第五句
for cell in i:
worksheet1.write_string(row, col, cell.value.strip()) # 首尾删特殊符号
col += 1
row += 1
new_book.close()
筛选出来的绝句
REFLECTION
1.第一次使用爬虫,不太熟悉,所以想着先爬下来再筛数据,下一次使用时,可在爬取数据的同时,做一些初筛(例如:删除空白、字符串前后字符等);
2.拆分诗句方法
1)可以试试直接读取字符串里面的字直到遇到不是中文,就记录并写入,拆分的准确度或许更高;
2)在拆分诗句的时候,还需要自己手动不断切换操作,可以试着让程序自己多次操作。
3.自己老陷入的误区是以为是在Excel表上进行删除以及移行等操作,实质上是读取旧文件的数据再写入到新文件,类似于刷新的操作。
Trip
Codelab-EIM
思路:通过EIM让Scratch传递表格坐标信息给Python,Python根据表格坐标信息,查询单元格的内容并传递回来,让Scratch存储,代码如下:
from codelab_adapter_client import run_monitor, send_message # adapter >= 4.3.0 or codelab-adapter-client >= 4.1.3
# from codelab_adapter_client.utils import run_monitor, send_simple_message
import platform
# 上面两句代码的意思是导入代码运行需要的依赖
import xlrd
# 打开表格准备读取
filename = 'poem_four.xlsx'
data = xlrd.open_workbook(filename)
table = data.sheet_by_name(u'sheet1')
def monitor(msg):# msg是Scratch传过来的消息
col = int(msg[0:1])
row = int(msg[1:])
poem = table.cell_value(row,col)# 读取表格指定单元格信息
return poem
while True:
run_monitor(monitor)# 传递消息给Scratch
Scratch程序
最终获得的Scratch列表
REFLECTION
1.最后才发现Scratch导出的列表是以txt的格式,也就是说其实可以直接用Python制作出诗句的txt文档也是可以实现效果的;
不过积累了经验,再使用到时,可以试着跳过中间转化成Excel的步骤,直接将数据存储到scratch中。
2.第一次使用EIM传递消息,为了图方便,就让python一直处在接收信息的状态,并没有设置退出条件。
Trip
项目式学习
最后分析一下这次项目式学习能够完成的原因:
1.问题的主观强相关
1)基于的问题与自己是强相关的,至少自己的主观上是认为完成后的成品对自己是有相当大的帮助的。(其实很有可能最后学生根本不想做,就完全用不上了,但只要主观不去这么想,那就是强相关🐶)
2)教学延展:在项目式教学中,我认为如何给学生营造出问题的主观强相关性,是项目开展的关键。
2.合适的脚手架
1)过程中互联网和自己的朋友们充当了脚手架,为我提供了很大的帮助,在此感谢!
2)教学延展:对于年龄较小的学生,互联网很难成为一个合适的脚手架,课堂上也很难让老师一个人成为所有学生的脚手架,就需要考虑如何在课堂上引入新的工具。
目前考虑的方向是提供一些可以参考的程序案例,可以让学生学习以及迁移使用。
3.明确(可清晰检验)的目标
1)任务拆分成几个部分后,都有比较明确的目标,每个目标有较明确的检验标准,比如诗句有没有爬到、诗句有没有分开、Scratch有没有收到消息。
2)教学延展:课堂上设定有清晰标准的任务目标,方便学生检验出目标的达成情况。
4.及时反馈
1)每个目标给自己的感觉,都是再花一点时间就能达成,我推测是因为每一次程序的输出都是一次及时的反馈,反馈能让自己意识到正在逐渐靠近想要达成的结果。
2)延展:及时给予学生任务进度的反馈,让学生意识到任务在不断往前推进。
Trip
附录
1.xpath
python学习之xpath使用案例总结如何查看网页元素的名称ID
https://blog.youkuaiyun.com/qq_42965915/article/details/108346932
2.爬虫协议
如何查看爬虫协议
https://blog.youkuaiyun.com/C0die/article/details/83794163
3.一些报错的bug
xlrd不支持xlsx格式的解决办法
https://blog.youkuaiyun.com/crud_player/article/details/119120377
Jupyter无法导入已安装的包
https://zhuanlan.zhihu.com/p/390887467
4.CodeLab-EIM
CodeLab Adapter
https://adapter.codelab.club/extension_guide/eim/
5.文中提到的文件分享
提取码: iue3