折腾:
【未解决】Python处理发布印象笔记帖子到WordPress后的部分细节优化
期间,发现之前帖子的代码,发布后,丢失了格式:

去看原贴是:

是有缩进的。
发布后,缩进都丢失了。
感觉是:soup转str,丢失了?
去找找原因
去调试,看看中间过程的html是什么样的
先去看看后台的html:
from evernote.edam.userstore.constants import * class Evernote(object): """ Operate Evernote Yinxiang note via python 首页 http://sandbox.yinxiang.com 登录 https://sandbox.yinxiang.com/Login.action?offer=www_menu Web版 主页

完全没有缩进了。
调试发现,原先是有空格的:
不过是div包括的:
<div>class Evernote(object):</div> <div> """</div> <div> Operate Evernote Yinxiang note via python</div> <div> <div><br /></div> </div> <div> 首页</div> <div> http://sandbox.yinxiang.com</div> <div> <div><br /></div>

继续调试,看看处理后是什么样的
codeStr = utils.getAllContents(eachCodeblockNode)
代码输出:
。。。 from evernote.edam.userstore.constants import * class Evernote(object): """ Operate Evernote Yinxiang note via python 首页 http://sandbox.yinxiang.com 登录 。。。
很明显,就没有缩进了:

那去:
【已解决】BeautifulSoup中如何保留div内的字符串且保留空格等缩进
然后整体字符串是:

有保留缩进的。
但是和原始内容比
中间的空行丢失了
所以再去想办法看看
“如果tag中包含多个字符串 [2] ,可以使用 .strings 来循环获取:
输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容:”
此处是没有我们要的 空行啊

还是少了空行。
突然意识到:

此次是印象笔记的笔记中的html是特殊的:
<div> <div><br /></div> </div>
用来表示空行的。
所以,需要此处特殊处理才可以。

以及用:
<div> <div><br /></div> <div><br /></div> </div>
表示2行。
所以要去写代码处理掉。
后来继续调试,至少好消息是:

后续内部的空格是可以保留的。
用代码:
# convert to newline eachCodeblockNode = convertDivBrToNewline(eachCodeblockNode) def convertDivBrToNewline(enCodeblockSoup): """Convert <div> <div><br /></div> </div> <div> <div><br /></div> <div><br /></div> </div> to: <div>\n</div> <div>\n\n</div> Args: enCodeblockSoup (Soup): soup of evernote post en-codeblock Returns: processed soup Raises: """ allBrSoupList = enCodeblockSoup.find_all("br") for eachBrSoup in allBrSoupList: isExpectedBr = False curBrParent = eachBrSoup.parent if curBrParent: curBrParentName = curBrParent.name isParentDiv = curBrParentName == "div" if isParentDiv: curBrParentParent = curBrParent.parent if curBrParentParent: curBrParentParentName = curBrParentParent.name if curBrParentParentName == "div": isExpectedBr = True if isExpectedBr: newlineStr = "\n" curBrParentParent.div.replace_with(newlineStr) # for debug afterConvertCodeStr = utils.getAllContents(enCodeblockSoup) logging.info("codeStr=%s", afterConvertCodeStr) return enCodeblockSoup
去调试。
调试发现,此处:
curBrParentParent.div.replace_with(newlineStr)
好像不对:万一div下面有2个:
<div><br/></div> <div><br/></div>
那:
curBrParentParent.div
好像就没法指定是哪个了。
好像参考
可以去:
insert_after() 一个 换行符
然后再销毁
或许就可以了?
不过此处暂时基本上实现了要的效果:

但是每次都是:单个空行,变成多个空行了。
还是去换成上面的先insert再销毁,看看效果
newlineStr = "\n" # newlineStr = enCodeblockSoup.new_string("\n") # curBrParentParent.div.replace_with(newlineStr) curBrParent.insert_after(newlineStr) curBrParent.decompose()
结果:
insert_after后,可以新增一个 \n

然后decompose后,curBrParentParent的确只剩一个,刚加上的:\n 了:

最后的字符串,貌似也是符合预期的:

只不过输出print好像是2个空行
继续试试
结果发现:
输出到log日志中的,的确是2个空行:

突然明白了:
此处无需加上换行:\n
只是加上 空行:””
if isExpectedBr: # newlineStr = "\n" # newlineStr = enCodeblockSoup.new_string("\n") # curBrParentParent.div.replace_with(newlineStr) # curBrParent.insert_after(newlineStr) emptylineStr = "" curBrParent.insert_after(emptylineStr) curBrParent.decompose()
估计就可以了。
去调试看看


输出整个字符串:

就正常了。
继续发布到WordPress中,后台编辑就正常有缩进和空行了:

预览后,也是正常有缩进和空行的:

【总结】
此处最终的改动是:
def convertDivBrToNewline(enCodeblockSoup): """Convert <div> <div><br /></div> </div> <div> <div><br /></div> <div><br /></div> </div> to: <div> </div> <div> </div> Args: enCodeblockSoup (Soup): soup of evernote post en-codeblock Returns: processed soup Raises: """ allBrSoupList = enCodeblockSoup.find_all("br") for eachBrSoup in allBrSoupList: isExpectedBr = False curBrParent = eachBrSoup.parent if curBrParent: curBrParentName = curBrParent.name isParentDiv = curBrParentName == "div" if isParentDiv: curBrParentParent = curBrParent.parent if curBrParentParent: curBrParentParentName = curBrParentParent.name if curBrParentParentName == "div": isExpectedBr = True if isExpectedBr: # newlineStr = "\n" # newlineStr = enCodeblockSoup.new_string("\n") # curBrParentParent.div.replace_with(newlineStr) # curBrParent.insert_after(newlineStr) emptylineStr = "" curBrParent.insert_after(emptylineStr) curBrParent.decompose() # # for debug # afterConvertCodeStr = utils.getAllContents(enCodeblockSoup) # logging.info("afterConvertCodeStr=%s", afterConvertCodeStr) return enCodeblockSoup def processPostCodeblock(soup): ... # convert to newline eachCodeblockNode = convertDivBrToNewline(eachCodeblockNode) codeStr = utils.getAllContents(eachCodeblockNode)
即可实现:
保留印象笔记的note的en-codeblock中的div中:
- br = 空行
- 空格 = 代码中的缩进
了。
相关函数:
libs/crifan/utils.py
def getAllContents(curNode, isStripped=False): """Get all contents of current and children nodes Args: curNode (soup node): current Beautifulsoup node isStripped (bool): return stripped string or not Returns: str Raises: """ # codeSnippetStr = curNode.prettify() # codeSnippetStr = curNode.string # codeSnippetStr = curNode.contents codeSnippetStr = "" stringList = [] if isStripped: stringGenerator = curNode.stripped_strings else: stringGenerator = curNode.strings # stringGenerator = curNode.strings for eachStr in stringGenerator: # logging.debug("eachStr=%s", eachStr) stringList.append(eachStr) codeSnippetStr = "\n".join(stringList) logging.debug("codeSnippetStr=%s", codeSnippetStr) return codeSnippetStr
最新代码详见: