python使用html2text库实现从HTML转markdown的方法详解


Posted in Python onFebruary 21, 2020

如果PyPi上搜html2text的话,找到的是另外一个库:Alir3z4/html2text。这个库是从aaronsw/html2text fork过来,并在此基础上对功能进行了扩展。因此是直接用pip安装的,因此本文主要来讲讲这个库。

首先,进行安装:

pip install html2text

命令行方式使用html2text

安装完后,就可以通过命令html2text进行一系列的操作了。

html2text命令使用方式为:html2text [(filename|url) [encoding]]。通过html2text -h,我们可以查看该命令支持的选项:

选项 描述
--version 显示程序版本号并退出
-h, --help 显示帮助信息并退出
--no-wrap-links 转换期间包装链接
--ignore-emphasis 对于强调,不包含任何格式
--reference-links 使用参考样式的链接,而不是内联链接
--ignore-links 对于链接,不包含任何格式
--protect-links 保护链接不换行,并用尖角括号将其围起来
--ignore-images 对于图像,不包含任何格式
--images-to-alt 丢弃图像数据,只保留替换文本
--images-with-size 将图像标签作为原生html,并带height和width属性,以保留维度
-g, --google-doc 转换一个被导出为html的谷歌文档
-d, --dash-unordered-list 对于无序列表,使用破折号而不是星号
-e, --asterisk-emphasis 对于被强调文本,使用星号而不是下划线
-b BODY_WIDTH, --body-width=BODY_WIDTH 每个输出行的字符数,0表示不自动换行
-i LIST_INDENT, --google-list-indent=LIST_INDENT Google缩进嵌套列表的像素数
-s, --hide-strikethrough 隐藏带删除线文本。只有当也指定-g的时候才有用
--escape-all 转义所有特殊字符。输出较为不可读,但是会避免极端情况下的格式化问题。
--bypass-tables 以HTML格式格式化表单,而不是Markdown语法。
--single-line-break 在一个块元素后使用单个换行符,而不是两个换行符。注意:要求?body-width=0
--unicode-snob 整个文档中都使用unicode
--no-automatic-links 在任何适用情况下,不要使用自动链接
--no-skip-internal-links 不要跳过内部链接
--links-after-para 将链接置于每段之后而不是文档之后
--mark-code 用 …将代码块标记出来
--decode-errors=DECODE_ERRORS 如何处理decode错误。接受值为'ignore', ‘strict'和'replace'

具体使用如下:

# 传递url
html2text http://eepurl.com/cK06Gn

# 传递文件名,编码方式设置为utf-8
html2text test.html utf-8

脚本中使用html2text

除了直接通过命令行使用html2text外,我们还可以在脚本中将其作为库导入。

我们以以下html文本为例

html_content = """
<span style="font-size:14px"><a href="http://blog.yhat.com/posts/visualize-nba-pipelines.html" rel="external nofollow" target="_blank" style="color: #1173C7;text-decoration: underline;font-weight: bold;">Data Wrangling 101: Using Python to Fetch, Manipulate & Visualize NBA Data</a></span><br>
A tutorial using pandas and a few other packages to build a simple datapipe for getting NBA data. Even though this tutorial is done using NBA data, you don't need to be an NBA fan to follow along. The same concepts and techniques can be applied to any project of your choosing.<br>
"""

一句话转换html文本为Markdown格式的文本:

import html2text
print html2text.html2text(html_content)

输出如下:

[Data Wrangling 101: Using Python to Fetch, Manipulate & Visualize NBA

Data](http://blog.yhat.com/posts/visualize-nba-pipelines.html)  

A tutorial using pandas and a few other packages to build a simple datapipe

for getting NBA data. Even though this tutorial is done using NBA data, you

don't need to be an NBA fan to follow along. The same concepts and techniques

can be applied to any project of your choosing.

另外,还可以使用上面的配置项:

import html2text
h = html2text.HTML2Text()
print h.handle(html_content) # 输出同上

注意:下面仅展示使用某个配置项时的输出,不使用某个配置项时使用默认值的输出(如无特殊说明)同上。

--ignore-emphasis

指定选项?ignore-emphasis

h.ignore_emphasis = True
print h.handle("<p>hello, this is <em>Ele</em></p>")

输出为:

hello, this is Ele

不指定选项?ignore-emphasis

h.ignore_emphasis = False # 默认值
print h.handle("<p>hello, this is <em>Ele</em></p>")

输出为:

hello, this is _Ele_

--reference-links

h.inline_links = False
print h.handle(html_content)

输出为:

[Data Wrangling 101: Using Python to Fetch, Manipulate & Visualize NBA

Data][16]  

A tutorial using pandas and a few other packages to build a simple datapipe

for getting NBA data. Even though this tutorial is done using NBA data, you

don't need to be an NBA fan to follow along. The same concepts and techniques

can be applied to any project of your choosing.  

   [16]: http://blog.yhat.com/posts/visualize-nba-pipelines.html

--ignore-links

h.ignore_links = True
print h.handle(html_content)

输出为:

Data Wrangling 101: Using Python to Fetch, Manipulate & Visualize NBA Data  

A tutorial using pandas and a few other packages to build a simple datapipe

for getting NBA data. Even though this tutorial is done using NBA data, you

don't need to be an NBA fan to follow along. The same concepts and techniques

can be applied to any project of your choosing.

--protect-links

h.protect_links = True
print h.handle(html_content)

输出为:

[Data Wrangling 101: Using Python to Fetch, Manipulate & Visualize NBA

Data](<http://blog.yhat.com/posts/visualize-nba-pipelines.html>)  

A tutorial using pandas and a few other packages to build a simple datapipe

for getting NBA data. Even though this tutorial is done using NBA data, you

don't need to be an NBA fan to follow along. The same concepts and techniques

can be applied to any project of your choosing.

--ignore-images

h.ignore_images = True
print h.handle('<p>This is a img: <img src="https://my.oschina.net/img/hot3.png" style="max-height: 32px; max-width: 32px;" alt="hot3"> ending ...</p>')

输出为:

This is a img:  ending ...

--images-to-alt

h.images_to_alt = True
print h.handle('<p>This is a img: <img src="https://my.oschina.net/img/hot3.png" style="max-height: 32px; max-width: 32px;" alt="hot3"> ending ...</p>')

输出为:

This is a img: hot3 ending ...

--images-with-size

h.images_with_size = True
print h.handle('<p>This is a img: <img src="https://my.oschina.net/img/hot3.png" height=32px width=32px alt="hot3"> ending ...</p>')

输出为:

This is a img: <img src='https://my.oschina.net/img/hot3.png' width='32px'

height='32px' alt='hot3' /> ending ...

--body-width

h.body_width=0
print h.handle(html_content)

输出为:

[Data Wrangling 101: Using Python to Fetch, Manipulate & Visualize NBA Data](http://blog.yhat.com/posts/visualize-nba-pipelines.html)  

A tutorial using pandas and a few other packages to build a simple datapipe for getting NBA data. Even though this tutorial is done using NBA data, you don't need to be an NBA fan to follow along. The same concepts and techniques can be applied to any project of your choosing.

--mark-code

h.mark_code=True
print h.handle('<pre class="hljs css"><code class="hljs css">    <span class="hljs-selector-tag"><span class="hljs-selector-tag">rpm</span></span> <span class="hljs-selector-tag"><span class="hljs-selector-tag">-Uvh</span></span> <span class="hljs-selector-tag"><span class="hljs-selector-tag">erlang-solutions-1</span></span><span class="hljs-selector-class"><span class="hljs-selector-class">.0-1</span></span><span class="hljs-selector-class"><span class="hljs-selector-class">.noarch</span></span><span class="hljs-selector-class"><span class="hljs-selector-class">.rpm</span></span></code></pre>')

输出为:

        rpm -Uvh erlang-solutions-1.0-1.noarch.rpm

通过这种方式,就可以以脚本的形式自定义HTML -> MARKDOWN的自动化过程了。例子可参考下面的例子

#-*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8') 
import re
import requests
from lxml import etree
import html2text


# 获取第一个issue
def get_first_issue(url):
  resp = requests.get(url)
  page = etree.HTML(resp.text)
  issue_list = page.xpath("//ul[@id='archive-list']/div[@class='display_archive']/li/a")
  fst_issue = issue_list[0].attrib
  fst_issue["text"] = issue_list[0].text
  return fst_issue


# 获取issue的内容,并转成markdown
def get_issue_md(url):
  resp = requests.get(url)
  page = etree.HTML(resp.text)
  content = page.xpath("//table[@id='templateBody']")[0]#'//table[@class="bodyTable"]')[0]
  h = html2text.HTML2Text()
  h.body_width=0 # 不自动换行
  return h.handle(etree.tostring(content))

subtitle_mapping = {
  '**From Our Sponsor**': '# 来自赞助商',
  '**News**': '# 新闻',
  '**Articles**,** Tutorials and Talks**': '# 文章,教程和讲座',
  '**Books**': '# 书籍',
  '**Interesting Projects, Tools and Libraries**': '# 好玩的项目,工具和库',
  '**Python Jobs of the Week**': '# 本周的Python工作',
  '**New Releases**': '# 最新发布',
  '**Upcoming Events and Webinars**': '# 近期活动和网络研讨会',
}
def clean_issue(content):
  # 去除‘Share Python Weekly'及后面部分
  content = re.sub('\*\*Share Python Weekly.*', '', content, flags=re.IGNORECASE)
  # 预处理标题
  for k, v in subtitle_mapping.items():
    content = content.replace(k, v)
  return content

tpl_str = """原文:[{title}]({url})
---
{content}
"""
def run():
  issue_list_url = "https://us2.campaign-archive.com/home/?u=e2e180baf855ac797ef407fc7&id=9e26887fc5"
  print "开始获取最新的issue……"
  fst = get_first_issue(issue_list_url)
  #fst = {'href': 'http://eepurl.com/dqpDyL', 'title': 'Python Weekly - Issue 341'}
  print "获取完毕。开始截取最新的issue内容并将其转换成markdown格式"
  content = get_issue_md(fst['href'])
  print "开始清理issue内容"
  content = clean_issue(content)

  print "清理完毕,准备将", fst['title'], "写入文件"
  title = fst['title'].replace('- ', '').replace(' ', '_')
  with open(title.strip()+'.md', "wb") as f:
    f.write(tpl_str.format(title=fst['title'], url=fst['href'], content=content))
  print "恭喜,完成啦。文件保存至%s.md" % title

if __name__ == '__main__':
  run()

这是一个每周跑一次的python weekly转markdown的脚本。

好啦,html2text就介绍到这里了。如果觉得它还不能满足你的要求,或者想添加更多的功能,可以fork并自行修改。

Python 相关文章推荐
ptyhon实现sitemap生成示例
Mar 30 Python
用Python脚本来删除指定容量以上的文件的教程
May 04 Python
JSON文件及Python对JSON文件的读写操作
Oct 07 Python
关于python下cv.waitKey无响应的原因及解决方法
Jan 10 Python
python做反被爬保护的方法
Jul 01 Python
Python之虚拟环境virtualenv,pipreqs生成项目依赖第三方包的方法
Jul 23 Python
HTML的form表单和django的form表单
Jul 25 Python
Python对接六大主流数据库(只需三步)
Jul 31 Python
Python FTP文件定时自动下载实现过程解析
Nov 12 Python
用 Python 制作地球仪的方法
Apr 24 Python
python 调用API接口 获取和解析 Json数据
Sep 28 Python
解决Python 写文件报错TypeError的问题
Oct 23 Python
python-sys.stdout作为默认函数参数的实现
Feb 21 #Python
pycharm运行程序时看不到任何结果显示的解决
Feb 21 #Python
Python 安装 virturalenv 虚拟环境的教程详解
Feb 21 #Python
python ffmpeg任意提取视频帧的方法
Feb 21 #Python
Python实现自动访问网页的例子
Feb 21 #Python
解决Python pip 自动更新升级失败的问题
Feb 21 #Python
python利用百度云接口实现车牌识别的示例
Feb 21 #Python
You might like
解析PHP强制转换类型及远程管理插件的安全隐患
2014/06/30 PHP
php读取目录及子目录下所有文件名的方法
2014/10/20 PHP
分享PHP函数实现数字与文字分页代码
2015/07/28 PHP
实例讲解如何在PHP的Yii框架中进行错误和异常处理
2016/03/17 PHP
PHP常见加密函数用法示例【crypt与md5】
2019/01/27 PHP
thinkphp5 + ajax 使用formdata提交数据(包括文件上传) 后台返回json完整实例
2020/03/02 PHP
Cookie 注入是怎样产生的
2009/04/08 Javascript
JS焦点图切换,上下翻转
2011/05/12 Javascript
js浏览器本地存储store.js介绍及应用
2014/05/13 Javascript
js计算德州扑克牌面值的方法
2015/03/04 Javascript
js运动应用实例解析
2015/12/28 Javascript
纯前端JavaScript实现Excel IO案例分享
2016/08/26 Javascript
基于BootStrap栅格栏系统完成网站底部版权信息区
2016/12/23 Javascript
基于jquery二维码生成插件qrcode
2017/01/07 Javascript
详解vue-cli与webpack结合如何处理静态资源
2017/09/19 Javascript
深入理解ES6 Promise 扩展always方法
2017/09/26 Javascript
vueScroll实现移动端下拉刷新、上拉加载
2019/03/22 Javascript
vue实现todolist功能、todolist组件拆分及todolist的删除功能
2019/04/11 Javascript
JavaScript常用内置对象用法分析
2019/07/09 Javascript
Node.js 实现抢票小工具 &amp; 短信通知提醒功能
2019/10/22 Javascript
vue实现计步器功能
2019/11/01 Javascript
使用Python程序抓取新浪在国内的所有IP的教程
2015/05/04 Python
使用pandas批量处理矢量化字符串的实例讲解
2018/07/10 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
2019/09/03 Python
Python命令行参数解析工具 docopt 安装和应用过程详解
2019/09/26 Python
python中字符串的编码与解码详析
2020/12/03 Python
html5 canvas绘制矩形和圆形的实例代码
2016/06/16 HTML / CSS
迷你西餐厅创业计划书范文
2013/12/31 职场文书
应届生如何写自荐信
2014/01/05 职场文书
2014年师德承诺书
2014/05/23 职场文书
幼儿园教师自荐书
2015/03/06 职场文书
Python趣味挑战之给幼儿园弟弟生成1000道算术题
2021/05/28 Python
Golang的继承模拟实例
2021/06/30 Golang
Win10/Win11 任务栏替换成经典样式
2022/04/19 数码科技
MySQL控制流函数(-if ,elseif,else,case...when)
2022/07/07 MySQL
Win10本地连接不见了怎么恢复? win10系统电脑本地连接不见了解决方法
2023/01/09 数码科技