最近一直带孩子在外面上英语外教课,机构的软件做得特别的好,尤其是自主学习里的RAZ分级阅读孩子很喜欢读,内容多,分级分得也到位,网上评价也很好, 可以点读,录音,上传,唯一不好的是没有纸质书,只能在app上阅读;于是就想着用python将app上的内容抓下来做成绘本的形式,再打印出来就是英语分级绘本了。
发现淘宝上很多这种打印版的英文绘本卖,不会我这个也可以卖钱吧,哈哈.
接下来我会将A级的90多篇全部抓下来做成绘本的形式,有需要给孩子准备的可以留言(email)分享给你们.你们可以自行打印。
原app绘本UI如下:
思路也挺简单:
1. 先是生成绘本的标题页,通过图2读取绘本的title.
2. 生成单词页,通过截取单词页图片&解释页图片,然后将单词&解释合并成一张图片,最后将多张单词&解释图片合成一张图片
3. 生成绘本内容页,通过截取绘本内容,然后将8张绘本图片合并成两页
4.将生成的4张内容图片打印出来就是一个亲子分级绘本了(刚好正反两面共两页,一页标题+单词、一页绘本内容)
效果如下, 当然彩色打印机效果更好,我们家是黑白打印机(A级总共有95篇,这是其中的一篇):
脚本如下, 供参考:
import os
import subprocess
from subprocess import Popen, PIPE
from PIL import Image # python -m pip install Pillow
from PIL import ImageFont
from PIL import ImageDraw
import uiautomator2 as u2 # python -m pip install --upgrade --pre uiautomator2
from time import sleep
import time
d = u2.connect_usb()
word_list = list() # 用于存储截取的单词图片name和单词解释图片name
word_explain_list = list() # 用于存储单词&解释合并后的图片name
cartoon_list = list() # 用于存储截取的绘本图片name
# 得到PC桌面路径
def getDesktopPath():
return 'C:\\Users\\' + os.getlogin() + '\\Desktop\\'
# 滑动屏幕
def screen_swipe():
d.swipe(1474, 0.5, 500, 0.5)
# 执行截图动作
def screenshot(path):
word_list.clear()
word_explain_list.clear()
cartoon_list.clear()
# 1. 标题页生成(本来是截图,但考虑到截图的背景色太复杂,打印时就太费耗材了)
strs = d.xpath("//*[contains(@resource-id, 'tv_bookTitle')]").get_text().strip()
titleImage = Image.new('RGB', (780, 470), 'white')
titleImage.save(path + '\\' + '001.jpg')
imagefile = path + '\\' + '001.jpg'
# 写入title时的字体信息
x, y = (220, 130) # 标题写入坐标value
font_size = 54 # 文字大小
font_css = "C:\\Windows\\Fonts\\JOKERMAN.TTF" # 字体文件
font = ImageFont.truetype(font_css,font_size)
# 写入姓名时的字体信息
x1, y1 = (426, 264) # 标题写入坐标value
font_size1 = 30 # 文字大小
font_css1 = "C:\\Windows\\Fonts\\TEMPSITC.TTF" # 字体文件
font1 = ImageFont.truetype(font_css1,font_size1)
name_time = f'Timmy {time.strftime("%Y-%m-%d", time.localtime())}'
im=Image.open(imagefile) # 打开图片
draw = ImageDraw.Draw(im)
draw.text((x, y), strs, (0, 0, 0), font=font) # 设置位置坐标、文字、颜色、字体
draw.text((x1, y1), name_time, (20, 20, 20), font=font1) # 设置位置坐标、文字、颜色、字体
im.save(path + '\\' + '001.jpg')
del draw
im.close()
# 2. 单词&解释截图
d.xpath("//*[contains(@text, '单词预习')]").click()
word_totalpage = int(d.xpath("//*[contains(@resource-id, 'tv_card_num')]").get_text().strip().split('/')[1])
word_cropbox = (762, 178, 1154, 684)
word_cropbox_explain = (762, 300, 1154, 450)
for imageId in range(1, word_totalpage*2+1):
# 获取反面的解释
if imageId%2 == 0:
d.click(0.5, 0.5)
# 切换至下一个页面
if imageId%2 == 1 and imageId != 1:
screen_swipe()
sleep(1)
word_name = f'word_{str(imageId)}.jpg'
# 截图的cmd
cmd = 'adb shell /system/bin/screencap -p /sdcard/' + word_name
if subprocess.run(cmd, shell=True).returncode == 0:
# 将截图文件copy至桌面的cmd
cmd = 'adb pull /sdcard/' + word_name + ' ' + path + '\\' + word_name
subprocess.run(cmd, shell=True)
# 删除sd卡中图片数据
subprocess.run('adb shell rm /sdcard/' + word_name, shell=True)
if imageId%2 == 0:
cropImage(word_cropbox_explain, word_name, path)
else:
cropImage(word_cropbox, word_name, path)
word_list.append(word_name)
mergeImage(word_list, 'word', path)
mergeImage(word_explain_list, 'word_explain', path)
d.press('back')
d.xpath("//*[contains(@text, '残忍离开')]").click()
sleep(1)
# 3. 绘本截图
d.xpath("//*[contains(@text, '绘本阅读')]").click()
d.xpath("//*[contains(@text, 'Start')]").click()
sleep(1)
cartoonbook_totalpage = int(d.xpath("//*[contains(@resource-id, 'tv_total_page_num')]").get_text().strip().split(' ')[1])
cartoonbook_cropbox = (360, 170, 1540, 980)
for imageId in range(1, cartoonbook_totalpage+1):
sleep(1)
cartoon_name = f'cartoon_{str(imageId)}.jpg'
# 截图的cmd
cmd = 'adb shell /system/bin/screencap -p /sdcard/' + cartoon_name
if subprocess.run(cmd, shell=True).returncode == 0:
# 将截图文件copy至桌面的cmd
cmd = 'adb pull /sdcard/' + cartoon_name + ' ' + path + '\\' + cartoon_name
subprocess.run(cmd, shell=True)
# 删除sd卡中图片数据
subprocess.run('adb shell rm /sdcard/' + cartoon_name, shell=True)
cropImage(cartoonbook_cropbox, cartoon_name, path)
cartoon_list.append(cartoon_name)
screen_swipe()
mergeImage(cartoon_list, 'cartoon', path)
d.press('back')
d.press('back')
d.press('back')
def cropImage(cropbox, filename, path):
imgfullpath = path + '\\' + filename
img = Image.open(imgfullpath)
newImg = img.crop(cropbox)
newImg.save(path + '\\' + filename)
def mergeImage(fileList, type, path):
# 1. 在单词截图和解释截图合并成一张图片
if type == 'word':
longImage = Image.new('RGB', (432, 696), 'white')
word_num = 1
for i in range(len(fileList)):
if i%2 != 0:
continue
word = Image.open(path + '\\' + fileList[i])
explain = Image.open(path + '\\' + fileList[i+1])
longImage.paste(word, (20, 20))
longImage.paste(explain, (20, 526))
filename = 'B' + str(word_num) + '.jpg'
longImage.save(path + '\\' + filename)
word_explain_list.append(filename)
os.remove(path + '\\' + fileList[i])
os.remove(path + '\\' + fileList[i+1])
word_num += 1
print(word_explain_list)
# 2. word&explain合并成一张图片
if type == 'word_explain':
word_explain_total = len(word_explain_list)
width = 392+40
if word_explain_total%5 != 0:
height = (int(word_explain_total/5) + 1)*(656+40)
else:
height = int(word_explain_total/5)*(656+40)
longImage = Image.new('RGB', (width*5+120, height), 'white')
line = 0
for i in range(word_explain_total):
im = Image.open(path + '\\' + word_explain_list[i])
if i%5 == 0:
longImage.paste(im, (0, line*676))
if i%5 == 1:
longImage.paste(im, (1*width, line*676))
if i%5 == 2:
longImage.paste(im, (2*width, line*676))
if i%5 == 3:
longImage.paste(im, (3*width, line*676))
if i%5 == 4:
longImage.paste(im, (4*width, line*676))
os.remove(path + '\\' + word_explain_list[i])
if (i+1)%5 == 0:
line += 1
longImage.save(path + '\\' + '002.jpg')
# 3. cartoonbok合并(每4张图片合成一张图片)
if type == 'cartoon':
cartoon_total = len(cartoon_list)
width, height = (1180+20+20, 810+20+20)
longImage = None
curpage_num = 0 # 当前页面已放置了几张图片
line = 0 # 当前页面的第几行
pageId = 3 # 当前页面被保存时的Id号
print(cartoon_list)
for i in range(cartoon_total):
if i%4 == 0:
longImage = Image.new('RGB', (width*2+120, height*2), 'white')
if curpage_num >= 2:
line = 1
if curpage_num >= 4:
line = 0
curpage_num = 0
im = Image.open(path + '\\' + cartoon_list[i])
if i%2 == 0:
if pageId%2 == 0:
longImage.paste(im, (0+20, line*height+20))
else:
longImage.paste(im, (0+20+120, line*height+20))
if i%2 == 1:
if pageId%2 == 0:
longImage.paste(im, (width+20, line*height+20))
else:
longImage.paste(im, (width+20+120, line*height+20))
curpage_num += 1
os.remove(path + '\\' + cartoon_list[i])
if (i+1)%4==0 or (i+1) == cartoon_total:
longImage.save(path + '\\' + f'00{pageId}.jpg')
pageId += 1
if __name__ == '__main__':
while True:
foldername = input('请输入当前绘本的Title(english):')
if foldername in ('end', 'END', 'End'):
break
# 新建文件夹和截图
path = getDesktopPath() +foldername
os.mkdir(path)
screenshot(path)