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 相关文章推荐
Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
Sep 06 Python
利用QT写一个极简单的图形化Python闹钟程序
Apr 07 Python
编写Python CGI脚本的教程
Jun 29 Python
Python读写Json涉及到中文的处理方法
Sep 12 Python
Python+matplotlib+numpy绘制精美的条形统计图
Jan 02 Python
15行Python代码带你轻松理解令牌桶算法
Mar 21 Python
pandas条件组合筛选和按范围筛选的示例代码
Aug 26 Python
Python中无限循环需要什么条件
May 27 Python
python程序如何进行保存
Jul 03 Python
python 调用API接口 获取和解析 Json数据
Sep 28 Python
python实现猜拳游戏项目
Nov 30 Python
详解Python模块化编程与装饰器
Jan 16 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的一个基础知识 表单提交
2011/07/04 PHP
php使用json_encode对变量json编码
2014/04/07 PHP
详细解读PHP中接口的应用
2015/08/12 PHP
PHP使用trim函数去除字符串左右空格及特殊字符实例
2016/01/07 PHP
一个非常实用的php文件上传类
2017/07/04 PHP
php插件Xajax使用方法详解
2017/08/31 PHP
ThinkPHP框架实现FTP图片上传功能示例
2019/04/08 PHP
js绑定事件this指向发生改变的问题解决方法
2013/04/23 Javascript
jquery cookie实现的简单换肤功能适合小网站
2013/08/25 Javascript
JS实现鼠标滑过折叠与展开菜单效果代码
2015/09/06 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
javascript实现一个简单的弹出窗
2016/02/22 Javascript
AngularJS的脏检查深入分析
2017/04/22 Javascript
vue2.0 父组件给子组件传递数据的方法
2018/01/15 Javascript
vue数据传递--我有特殊的实现技巧
2018/03/20 Javascript
[46:09]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第三场
2014/05/26 DOTA
[16:56]教你分分钟做大人:司夜刺客
2014/10/30 DOTA
python 打印对象的所有属性值的方法
2016/09/11 Python
python 筛选数据集中列中value长度大于20的数据集方法
2018/06/14 Python
在python中将字符串转为json对象并取值的方法
2018/12/31 Python
Python基于滑动平均思想实现缺失数据填充的方法
2019/02/21 Python
pytorch 图像预处理之减去均值,除以方差的实例
2020/01/02 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
2020/01/09 Python
PyTorch加载自己的数据集实例详解
2020/03/18 Python
python3.6使用SMTP协议发送邮件
2020/05/20 Python
解决python3中os.popen()出错的问题
2020/11/19 Python
python中round函数保留两位小数的方法
2020/12/04 Python
圣彼得堡鲜花配送:Semicvetic
2020/09/15 全球购物
初婚初育证明
2014/01/14 职场文书
教师党员公开承诺书
2014/03/25 职场文书
小学教师暑期培训方案
2014/08/28 职场文书
医院见习报告范文
2014/11/03 职场文书
培训班开班主持词
2015/07/02 职场文书
2016年公务员六五普法心得体会
2016/01/21 职场文书
pytorch显存一直变大的解决方案
2021/04/08 Python
使用Oracle命令进行数据库备份与还原
2021/12/06 Oracle