利用beautifulsoup4解析Kindle笔记

目录

1.需求说明

拥有Kindle Paperwhite 3 ( KPW3 )设备,平常会在KPW3、android手机、ipad及电脑等多端设备阅读电子书,阅读过程中会对书籍标记、做笔记,比较奇怪的是KPW3上的标记、笔记能同步到其他终端上,反过来虽然可以同步到KPW3上,但是标注及笔记无法记录到My Clippings.txt,以至于无法进一步加工处理读书笔记,所以利用android手机的kindle的笔记导出功能,将一本书籍的所有笔记以html导出,进一步解析合并至My Clippings.txt及处理到Variety、anki等应用上。

2.系统环境

  1. #系统环境 
  2. !lsb_release -a 
  1. No LSB modules are available. 
  2. Distributor ID: LinuxMint 
  3. Description: Linux Mint 19.3 Tricia 
  4. Release: 19.3 
  5. Codename: tricia 
  1. #Python及相关库版本 
  2. !python --version 
  3. !python -m pip list --format=columns | grep beautifulsoup4 
  4. !python -m pip list --format=columns | grep lxml 
  1. Python 3.6.9 
  2. beautifulsoup4 4.9.0  
  3. lxml 4.5.0  

3.利用app版kindle导出读书笔记

确保android上的Kindle笔记已经完整(可能出现手机1笔记完整,手机2只有一个字,如下图,这种情况只能定位过去再标记一遍)

多端同步出现笔记不一致问题
多端同步出现笔记不一致问题

笔记完整后,使用无格式导出笔记,导出流程如下图:

第一步 第二步

笔记导出后,效果如下图:

导出的kindle笔记
导出的kindle笔记

4.解析html笔记

4.1解析书籍基本信息

  1. #导入库 
  2. import re 
  3. from bs4 import BeautifulSoup 
  4. from lxml.html.clean import unicode 
  5.  
  6. #创建Beautifulsoup对象 
  7. soup=BeautifulSoup(open('./demo.html'),features='html.parser') 
  8.  
  9. #获取书籍名称及作者 
  10. bookname=soup.find_all('div',class_='bookTitle')[0].text.strip() 
  11. authors=soup.find_all('div',class_='authors')[0].text.strip() 
  12. print(bookname,authors) 
  1. 拆掉思维里的墙:原来我还可以这样活 古典 

4.2解析书籍笔记

  1. #所有笔记内容 
  2. allcontents=soup.contents[3].contents[3].contents[1] 
  3.  
  4. #遍历所有笔记内容 
  5. allnotes=[] 
  6. takenoteflag=False 
  7. for conind in range(11,len(allcontents)): 
  8. content=BeautifulSoup(unicode(allcontents.contents[conind])) 
  9. if len(content)==0: 
  10. continue 
  11. if conind==11: 
  12. note={'sectionHeading':'','noteHeading':{'markColor':'','markPosition':''},'noteText':'','takenote':{'takePosition':'','note':''}}  
  13. #根据css样式区分内容 
  14. div=content.select('div') 
  15. divclass=div[0].get("class")[0] 
  16. #笔记所处章节 
  17. if divclass=='sectionHeading': 
  18. note['sectionHeading']=content.text.strip().replace('\n','') 
  19. #笔记样式 
  20. elif divclass=='noteHeading': 
  21. if takenoteflag: 
  22. markpos=re.findall(r'\d+',content.text.strip().replace('\n',''))[0] 
  23. note['takenote']['markPosition']=markpos 
  24. else: 
  25. markclo=content.span.text.strip().replace('\n','') 
  26. markpos=re.findall(r'\d+',content.text.strip().replace('\n',''))[0] 
  27. note['noteHeading']['markColor']=markclo 
  28. note['noteHeading']['markPosition']=markpos 
  29. #自己做了笔记 
  30. elif divclass=='noteText' and takenoteflag: 
  31. note['takenote']['note']=content.text.strip().replace('\n','') 
  32. takenoteflag=False 
  33. allnotes.append(note) 
  34. note={'sectionHeading':note['sectionHeading'],'noteHeading':{'markColor':'','markPosition':''},'noteText':'','takenote':{'takePosition':'','note':''}} 
  35. #仅仅是标记笔记 
  36. elif divclass=='noteText' and not takenoteflag: 
  37. note['noteText']=content.text.strip().replace('\n','') 
  38.  
  39. #判断后续是否有笔记 
  40. strtind=1 
  41. nextnote=BeautifulSoup(unicode(allcontents.contents[conind+strtind])) 
  42. while len(nextnote)==0 and (conind+strtind)<len(allcontents): 
  43. nextnote=BeautifulSoup(unicode(allcontents.contents[conind+strtind])) 
  44. strtind+=1 
  45. if '笔记' in nextnote.text.strip().replace('\n',''): 
  46. takenoteflag=True 
  47. else: 
  48. allnotes.append(note) 
  49. note={'sectionHeading':note['sectionHeading'],'noteHeading':{'markColor':'','markPosition':''},'noteText':'','takenote':{'takePosition':'','note':''}} 
  50. # print(allnotes) 

5.应用html笔记

5.1追加至kindle笔记管理文件My Clippings.txt

解析了笔记内容,按照My Clippings.txt文件中的标记、笔记格式,将导出笔记内容追加至My Clippings.txt,笔记合并后,可利用现有的诸如clippings.io书见等工具进行笔记管理。

注意:由于导出笔记不含时间信息,因此至获取当前系统时间作为笔记时间,该时间非真实做笔记时间

  1. #获取当前时间 
  2. import time 
  3. def Getnowdate(): 
  4. week_day_dict = { 
  5. 0 : '星期一', 
  6. 1 : '星期二', 
  7. 2 : '星期三', 
  8. 3 : '星期四', 
  9. 4 : '星期五', 
  10. 5 : '星期六', 
  11. 6 : '星期天', 
  12. } 
  13. loctime=time.localtime() 
  14. years=time.strftime("%Y年%-m月%-d日", loctime) 
  15. weeks=week_day_dict[loctime[6]] 
  16.  
  17. if loctime[3]<=12: 
  18. times=time.strftime("上午%-H:%-M:%S", loctime) 
  19. else: 
  20. times='下午'+time.localtime()[3]-12+time.strftime(":%M:%S", loctime) 
  21. nowdate=years+weeks+' '+times 
  22. return nowdate 
  1. #读入已做的笔记 
  2. existnotes=open('My Clippings.txt','r').readlines() 
  3.  
  4. #写入文件 
  5. fw=open('My Clippings.txt','a') 
  6. for noteind in range(0,len(allnotes)): 
  7. if allnotes[noteind]['takenote']['note']!='': 
  8.  
  9. if (allnotes[noteind]['noteText'].replace(' ','')+'\n') not in existnotes: 
  10. fw.write(bookname+' ('+authors+')\n') 
  11. fw.write('- 您在位置 #'+allnotes[noteind]['noteHeading']['markPosition']+'-'+str(int(allnotes[noteind]['noteHeading']['markPosition'])+1)+' 的标注'+' | 添加于 '+Getnowdate()+'\n\n') 
  12. fw.write(allnotes[noteind]['noteText'].replace(' ','')+'\n') 
  13. fw.write('==========\n') 
  14.  
  15. if (allnotes[noteind]['takenote']['note'].replace(' ','')+'\n') not in existnotes: 
  16. fw.write(bookname+' ('+authors+')\n') 
  17. fw.write('- 您在位置 #'+allnotes[noteind]['noteHeading']['markPosition']+' 的笔记'+' | 添加于 '+Getnowdate()+'\n\n') 
  18. fw.write(allnotes[noteind]['takenote']['note']+'\n') 
  19. fw.write('==========\n')  
  20.  
  21. else: 
  22. if (allnotes[noteind]['noteText'].replace(' ','')+'\n') not in existnotes: 
  23. fw.write(bookname+' ('+authors+')\n') 
  24. fw.write('- 您在位置 #'+allnotes[noteind]['noteHeading']['markPosition']+'-'+str(int(allnotes[noteind]['noteHeading']['markPosition'])+1)+' 的标注'+' | 添加于 '+Getnowdate()+'\n\n') 
  25. fw.write(allnotes[noteind]['noteText'].replace(' ','')+'\n') 
  26. fw.write('==========\n')  
  27. fw.close() 

将读书笔记追加至My Clippings.txt
将读书笔记追加至My Clippings.txt

5.2适配成Variety箴言

Variety是linux下的壁纸管理工具,具备使用本地文档显示箴言的功能,现将kindle笔记解析成Variety识别的格式,并展示出来,方便日常查看。

  1. #读入已做的笔记 
  2. #处理已添加的箴言 
  3. def Delline(line): 
  4. lastind=0 
  5. if '[' in line: 
  6. lastind=line.index('[') 
  7. return line[:lastind] 
  8.  
  9. existnotes=list(map(Delline,open('/home/wu/.config/variety/pluginconfig/quotes/qotes.txt','r').readlines())) 
  10.  
  11. #写入文件 
  12. fw=open('qotes.txt','w') 
  13. for noteind in range(0,len(allnotes)): 
  14. if allnotes[noteind]['noteText'].replace(' ','') not in existnotes: 
  15. fw.write(allnotes[noteind]['noteText'].replace(' ','')+'['+allnotes[noteind]['sectionHeading'].replace(' ','')+']'+'——'+bookname+' ('+authors+')\n') 
  16. if allnotes[noteind]['takenote']['note'].replace(' ','')!='': 
  17. fw.write('#'+allnotes[noteind]['takenote']['note'].replace(' ','')+'——@'+'WuShaogui\n') 
  18. fw.write('.\n') 
  19. fw.close() 
解析后的文档 Variety配置

Variety箴言显示效果
Variety箴言显示效果

5.3匹配成anki笔记模式

anki是背书神器,将kindle笔记导入anki中,可以对一本书的笔记进行反复的练习,加深感悟!

  1. #写入anki笔记导入格式 
  2. fw=open('%s-%s.txt'%(bookname,authors),'w') 
  3. for noteind in range(0,len(allnotes)): 
  4. fw.write(allnotes[noteind]['noteText'].replace(' ','')+'\t'\ 
  5. +allnotes[noteind]['sectionHeading'].replace(' ','')+'\t'\ 
  6. +bookname+'\t'+authors+'\t'+allnotes[noteind]['takenote']['note'].replace(' ','')+'\n') 
  7. fw.close() 
解析后的文档 Anki导入解析后文档
文档导入后效果 最终效果图
posted @ 2020-05-14 08:56  好奇不止,探索不息  阅读(687)  评论(1编辑  收藏  举报