日本語の
このBlogの
ライブラリの インストール
Python-Markdownと、
!pip install markdown !pip install budoux
BudouX の 動作確認
インストール後、
import budoux parser = budoux.load_default_japanese_parser() print(parser.parse('今日は晴れています。')) print(parser.translate_html_string('今日は晴れています。'))
['今日は', '晴れています。'] <span style="word-break: keep-all; overflow-wrap: break-word;">今日は<wbr>晴れています。。</span>
テキストにparse
とtranslate_html_string
と
Python-Markdown の 拡張ポイントに ついて
Python-Markdown には、
これは
今回実施したいのは、
Python-Markdownには、
処理フェーズごとに
- 前処理を
行う preprocessor。 - ブロックレベルの
処理を 行い、 ElementTreeに する blockprocessor。 - ElementTreeに
対して 処理を 行う treeprocessor。 - treeprocessorから
呼び出される inlineprocessor。 - 後処理を
行う postprocessor。
今回拡張が
BudouXHashHeaderProcessor と、
import markdown import re import xml.etree.ElementTree as etree from markdown.blockprocessors import BlockProcessor, BlockParser,EmptyBlockProcessor,ListIndentProcessor,CodeBlockProcessor,HashHeaderProcessor,SetextHeaderProcessor,HRProcessor,OListProcessor,UListProcessor,BlockQuoteProcessor, ReferenceProcessor, ParagraphProcessor # BudouXのインポート、parserの生成 import budoux parser = budoux.load_default_japanese_parser() import logging logger = logging.getLogger("TEST") # BudouX を呼びだしを行うProcessorクラス その1 (これはヘッダーに対して処理を行う) class BudouXHashHeaderProcessor(BlockProcessor): """ Process Hash Headers. """ # Detect a header at start of any line in block RE = re.compile(r'(?:^|\n)(?P<level>#{1,6})(?P<header>(?:\\.|[^\\])*?)#*(?:\n|$)') def test(self, parent, block): return bool(self.RE.search(block)) def run(self, parent, blocks): block = blocks.pop(0) m = self.RE.search(block) if m: before = block[:m.start()] # All lines before header after = block[m.end():] # All lines after header if before: # As the header was not the first line of the block and the # lines before the header must be parsed first, # recursively parse this lines as a block. self.parser.parseBlocks(parent, [before]) # Create header using named groups from RE h = etree.SubElement(parent, 'h%d' % len(m.group('level'))) h.text = m.group('header').strip() # BudouXでテキスト加工 h.text = parser.translate_html_string(h.text) if after: # Insert remaining lines as first block for future parsing. blocks.insert(0, after) else: # pragma: no cover # This should never happen, but just in case... logger.warn("We've got a problem header: %r" % block) class BudouXParagraphProcessor(BlockProcessor): """ Process Paragraph blocks. """ def test(self, parent, block): return True def run(self, parent, blocks): block = blocks.pop(0) if block.strip(): # Not a blank block. Add to parent, otherwise throw it away. if self.parser.state.isstate('list'): # The parent is a tight-list. # # Check for any children. This will likely only happen in a # tight-list when a header isn't followed by a blank line. # For example: # # * # Header # Line 2 of list item - not part of header. sibling = self.lastChild(parent) if sibling is not None: # Insetrt after sibling. if sibling.tail: # BudouXでテキスト加工 文字列が存在するので改行処理の前に実施 sibling.tail = parser.translate_html_string(sibling.tail) sibling.tail = '{}\n{}'.format(sibling.tail, block) else: sibling.tail = '\n%s' % block # BudouXでテキスト加工 sibling.tail = parser.translate_html_string(sibling.tail) else: # Append to parent.text if parent.text: # BudouXでテキスト加工 文字列が存在するので改行処理の前に実施 parent.text = parser.translate_html_string(parent.text) parent.text = '{}\n{}'.format(parent.text, block) else: parent.text = block.lstrip() # BudouXでテキスト加工 parent.text = parser.translate_html_string(parent.text) else: # Create a regular paragraph p = etree.SubElement(parent, 'p') p.text = block.lstrip() # BudouXでテキスト加工 p.text = parser.translate_html_string(p.text) # blockprocessors の登録処理 def build_block_parser(md, **kwargs): """ Build the default block parser used by Markdown. """ parser = BlockParser(md) parser.blockprocessors.register(EmptyBlockProcessor(parser), 'empty', 100) parser.blockprocessors.register(ListIndentProcessor(parser), 'indent', 90) parser.blockprocessors.register(CodeBlockProcessor(parser), 'code', 80) parser.blockprocessors.register(BudouXHashHeaderProcessor(parser), 'hashheader', 70) parser.blockprocessors.register(SetextHeaderProcessor(parser), 'setextheader', 60) parser.blockprocessors.register(HRProcessor(parser), 'hr', 50) parser.blockprocessors.register(OListProcessor(parser), 'olist', 40) parser.blockprocessors.register(UListProcessor(parser), 'ulist', 30) parser.blockprocessors.register(BlockQuoteProcessor(parser), 'quote', 20) parser.blockprocessors.register(ReferenceProcessor(parser), 'reference', 15) parser.blockprocessors.register(BudouXParagraphProcessor(parser), 'paragraph', 10) return parser # Markdown > HTML変換 md = markdown.Markdown(); # デフォルトのparserを変更 md.parser = build_block_parser(md) html = md.convert(""" ------------ ## 感想、思ったこと 以下調べて思ったことになります。 * New Relic、DataDog、 Mackerel が多い。個人的に観測していた肌感とは一致した。 * Cloudwatch の印象が変わった。New Relic、DataDog等 と似たようなことはできそう。 * Sentry系のツールはそれなりに利用実績がある。統合監視って訳ではないのだろうが、フロントエンド監視に特化していて、フロントエンド監視をしたいというユースケースが多いように思えた。 * Prometheus、Grafanaの組み合わせは、オンプレミス環境で使われてそう。 * Zabbixは枯れてはいるが、プラグインインストールでモダンなこともできそう。 企業利用を軸で調べたことでツールへの先入観が消えました。 機能の比較とともに、各社何故使っているのかを考えると、自社に適用していくときの判断材料になりそうに思います。 --- ## 参考 以下、参考にした記事になります。 * [Googleの「AMP優遇」がまもなく終了 - GIGAZINE](https://gigazine.net/news/20210519-google-amp-no-longer-preferential-treatment/) Django 1.x から Django 3.x へのアップデートになり、Mezzanine というか Django のプラグインでのエラーが大量に発生しました。 なかなかエラーを解消できず、2-3時間サイト停止させてしまいました。。 事前の検証はやっておいたほうが良いかなと思いました。 """) # 標準出力 print(html)
<hr /> <h2><span style="word-break: keep-all; overflow-wrap: break-word;">感想、<wbr>思った<wbr>こと</span></h2> <p><span style="word-break: keep-all; overflow-wrap: break-word;">以下調べて<wbr>思った<wbr>ことになります。<wbr> </span></p> <ul> <li><span style="word-break: keep-all; overflow-wrap: break-word;">New Relic、<wbr>DataDog、<wbr> Mackerel が<wbr>多い。<wbr>個人的に<wbr>観測していた<wbr>肌感とは<wbr>一致した。<wbr> </span></li> <li><span style="word-break: keep-all; overflow-wrap: break-word;">Cloudwatch の<wbr>印象が<wbr>変わった。<wbr>New Relic、<wbr>DataDog等 と<wbr>似たようなことは<wbr>できそう。<wbr> </span></li> <li><span style="word-break: keep-all; overflow-wrap: break-word;">Sentry系の<wbr>ツールは<wbr>それなりに<wbr>利用実績が<wbr>ある。<wbr>統合監視って<wbr>訳ではないのだろうが、<wbr>フロントエンド監視に<wbr>特化していて、<wbr>フロントエンド監視を<wbr>したいと<wbr>いう<wbr>ユースケースが<wbr>多いように<wbr>思えた。<wbr> </span></li> <li><span style="word-break: keep-all; overflow-wrap: break-word;">Prometheus、<wbr>Grafanaの<wbr>組み合わせは、<wbr>オンプレミス環境で<wbr>使われてそう。<wbr> </span></li> <li><span style="word-break: keep-all; overflow-wrap: break-word;">Zabbixは<wbr>枯れては<wbr>いるが、<wbr>プラグインインストールで<wbr>モダンな<wbr>こともできそう。<wbr> </span></li> </ul> <p><span style="word-break: keep-all; overflow-wrap: break-word;">企業利用を<wbr>軸で<wbr>調べた<wbr>ことで<wbr>ツールへの<wbr>先入観が<wbr>消えました。<wbr> <br /> 機能の<wbr>比較とともに、<wbr>各社何故使っているのかを<wbr>考えると、<wbr>自社に<wbr>適用していく<wbr>ときの<wbr>判断材料に<wbr>なりそうに<wbr>思います。<wbr> </span></p> <hr /> <h2><span style="word-break: keep-all; overflow-wrap: break-word;">参考</span></h2> <p><span style="word-break: keep-all; overflow-wrap: break-word;">以下、<wbr>参考に<wbr>した<wbr>記事に<wbr>なります。<wbr> </span></p> <ul> <li><span style="word-break: keep-all; overflow-wrap: break-word;"><a href="https://gigazine.net/news/20210519-google-amp-no-longer-preferential-treatment/">Googleの<wbr>「AMP優遇」が<wbr>まも<wbr>なく<wbr>終了 - GIGAZINE</a> </span></li> </ul> <p><span style="word-break: keep-all; overflow-wrap: break-word;">Django 1.x から<wbr> Django 3.x への<wbr>アップデートに<wbr>なり、<wbr>Mezzanine と<wbr>いうか Django の<wbr>プラグインでの<wbr>エラーが<wbr>大量に<wbr>発生しました。<wbr> <br /> なかなか<wbr>エラーを<wbr>解消できず、<wbr>2-3時間<wbr>サイト停止させてしまいました。。<wbr> <br /> 事前の<wbr>検証は<wbr>やっておいた<wbr>ほうが<wbr>良いかなと<wbr>思いました。<wbr> </span></p>
期待通り
実施に
参考
記事作成時に
- 【Python】
Python-Markdownで 拡張機能を 追加する (その 1) - 【Python】
Python-Markdownで 拡張機能を 追加する (その 2) - Python-Markdownの
ソースを 読んでみる :パーサの 作り方 - Qiita
以上です。
コメント