好好学习,天天向上

好物推荐|从HTML到markdown - html2text

西溪植物园饱满的蒲公英

正题之前,先碎碎念几句。

Ele近来对系列文略感兴趣,因此准备开一个好物推荐的系列文,讲讲工作生活中用到的小而美的东东(可能是某些库,工具之类的)。算是雁过留痕,以备后续翻阅吧。

好啦,絮絮叨叨的话讲完了,我们进入正题吧。

话说这近一年来,Ele少数不多坚持下来的事情就是python-doc了。一开始仅仅是为了入门python顺便练练专业英语,虽然到后面有所懈怠,但是每周不翻一次Python Weekly总觉得亏欠了谁什么似的。因为放在github上,所以当初选择了markdown作为文本格式。

但是,Ele翻的文章都是在网上找的,因此需要将HTML转成markdown。

一开始,Ele用的是在线的HTML转MarkDown工具。这个工具虽好,但是对我而言却有几个问题: * 每次都要打开文章,然后F12找到文章正文 * 对代码块的支持很差,转出来的markdown文本里面的代码块都是原生的HTML文本。所以转后还得对结果里面的代码块再一次进行处理 * 对每篇文章都得重复上面的过程

由于这个过程都是可重复的,因此,此时不自动化更待何时呢?本着造轮子之前先找找有没有轮子的精神,Ele在github上找到了库:aaronsw/html2text

这个库是用python写的,它可以把html文本转成干净易读的纯ASCII文本,并且文本是有效的markdown格式。

BINGO!!!github大法好~~

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

首先,进行安装:

1
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 用[code]...[/code]将代码块标记出来
--decode-errors=DECODE_ERRORS 如何处理decode错误。接受值为'ignore', 'strict'和'replace'

具体使用如下:

1
2
3
4
5
# 传递url
html2text http://eepurl.com/cK06Gn

# 传递文件名,编码方式设置为utf-8
html2text test.html utf-8
### 脚本中使用html2text 除了直接通过命令行使用html2text外,我们还可以在脚本中将其作为库导入。

我们以以下html文本为例

1
2
3
4
html_content = """
<span style="font-size:14px"><a href="http://blog.yhat.com/posts/visualize-nba-pipelines.html" target="_blank" style="color: #1173C7;text-decoration: underline;font-weight: bold;">Data Wrangling 101: Using Python to Fetch, Manipulate &amp; 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格式的文本:
1
2
import html2text
print html2text.html2text(html_content)
输出如下:
1
2
3
4
5
6
[Data Wrangling 101: Using Python to Fetch, Manipulate &amp; 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.
另外,还可以使用上面的配置项:
1
2
3
import html2text
h = html2text.HTML2Text()
print h.handle(html_content) # 输出同上
> 注意:下面仅展示使用某个配置项时的输出,不使用某个配置项时使用默认值的输出(如无特殊说明)同上。

  • --ignore-emphasis

    • 指定选项--ignore-emphasis
      1
      2
      h.ignore_emphasis = True
      print h.handle("<p>hello, this is <em>Ele</em></p>")
      输出为:
      1
      hello, this is Ele 
    • 不指定选项--ignore-emphasis
      1
      2
      h.ignore_emphasis = False # 默认值
      print h.handle("<p>hello, this is <em>Ele</em></p>")
      输出为:
      1
      hello, this is _Ele_
  • --reference-links

    1
    2
    h.inline_links = False
    print h.handle(html_content)
    输出为:
    1
    2
    3
    4
    5
    6
    7
    8
    [Data Wrangling 101: Using Python to Fetch, Manipulate &amp; 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

    1
    2
    h.ignore_links = True
    print h.handle(html_content)
    输出为:
    1
    2
    3
    4
    5
    Data Wrangling 101: Using Python to Fetch, Manipulate &amp; 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

    1
    2
    h.protect_links = True
    print h.handle(html_content)
    输出为:
    1
    2
    3
    4
    5
    6
    [Data Wrangling 101: Using Python to Fetch, Manipulate &amp; 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

    1
    2
    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>')
    输出为:
    1
    This is a img:  ending ...

  • --images-to-alt

    1
    2
    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>')
    输出为:
    1
    This is a img: hot3 ending ...

  • --images-with-size

    1
    2
    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>')
    输出为:
    1
    2
    This is a img: <img src='https://my.oschina.net/img/hot3.png' width='32px'
    height='32px' alt='hot3' /> ending ...

  • --body-width

    1
    2
    h.body_width=0
    print h.handle(html_content)
    输出为:
    1
    2
    [Data Wrangling 101: Using Python to Fetch, Manipulate &amp; 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

    1
    2
    h.mark_code=True
    print h.handle('<pre class="hljs css"><code class="hljs css">&nbsp;&nbsp;&nbsp;&nbsp;<span class="hljs-selector-tag"><span class="hljs-selector-tag">rpm</span></span>&nbsp;<span class="hljs-selector-tag"><span class="hljs-selector-tag">-Uvh</span></span>&nbsp;<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>')
    输出为:
    1
    2
    3
    4
    [code]

    rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
    [/code]

通过这种方式,就可以以脚本的形式自定义HTML -> MARKDOWN的自动化过程了。例子可参考pw2md,这是一个每周跑一次的python weekly转markdown的脚本。

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

请言小午吃个甜筒~~