Open10

Web ページを 丸ごと Notion にコピーする

nikogolinikogoli

0. モチベ

前々から考えていて、Zenn については一応できるようになったやつ。
どっかに書いたけど、リンクからブックマークを作成しても後で読まないので、ブックマークではなくページの「中身」を Notion に移そう、っていうもの。

で、問題になるのが

  • あらゆる web ページで利用可能な
  • ページの html から『Notion に機械的に変換可能な記事の部分』を取り出す仕組み

とはどんなもの? ってこと。

以前に Zenn の article / scrap と note の3つを対象にして機能するものをつくってみたところ辛すぎて断念したのだけど、やっぱりまた欲しくなったので再検討してみる。

nikogolinikogoli

1. とりあえず『記事の部分』を見つける

試してみたことがある手法

  • article タグ / main タグ / id="content**" / id="main**" の div を起点

微妙。思ったよりも「正答率」が低く、「誤答」の場合は正解にたどり着けない。
さらに問題なのは、ほぼ全ての場合においてこれらの要素の直下が『記事の部分』というわけではないので、これらが見つかってもあまり役立たない。

nikogolinikogoli

で、さっき思いついたのが、「上から順に占有面積が広い要素を降りていく」手法。
普通に駄目だった。そりゃ .html 状態の HTML はサイズの情報を持たないよね...

どのみち停止基準が重要なのは同じなので、それで掘っていくしかないか

nikogolinikogoli

以前にまとめたやつ

nikogolinikogoli

HTMLで並列に存在する要素と notion の block の対応

1対1で変換できる基本的なやつ

elem.nodeName block_type
H1 heading_1
H2 heading_2
H3 heading_3
BR paragraph
HR divider
TABLE table
UL bulleted_list_item
OL numbered_list_item
P paragraph
BLOCKQUOTE quote
IMG image / embed

基本的ではないもの

  • A
    現代のブログ/記事ではリンクが素置きされることは珍しく、多くの場合カード化等が行われる
    無視? or display: 等の attr を確認して対処?
    → 基本は無視で、切り替え可能に
  • iframe による埋め込み
  • DIV
  • コード系
    pre や div、figure など囲みタグは色々ある
    class: ~codeを見て、そこを起点に文字列を引き出す
nikogolinikogoli

p の中身

基本

改行 リンク 上付き コード 強調 打ち消し線 斜体
BR A SUP CODE STRONG / b S EM / i
2つ続けば
空行を追加
リンク化 リンク化 コード化 bold 打ち消し線 斜体

その他

  • IMG
  • 数式系EMBED-KATEXNWC-FORMULA
nikogolinikogoli

組み立て

  • ベース処理:H1 / H2 / H3 / BR / HR / TABLE / UL / OL / P / BLOCKQUOTE / IMG
  • A の処理
  • P の中身の処理

どっち基準で処理するか?

  1. html → notion:switch タグ: return ブロック
  2. html ← notion:タグ → ブロック名; switch ブロック名: return ブロック

基準化しやすい2のほうが良い?

nikogolinikogoli

ネスト周りの話

ネストと疑似的ページまわり
  • 通常、文章要素とそれ以外の要素は区別され、並列に並ぶ

  • 「文章要素」は <p>で囲まれる

  • 「文章以外の要素」における例外として、画像は必ず <p>で囲まれる。
    md において上下の文章との間に空行がなければ、これらの文章とまとめて囲まれる

  • <li>の中では、文章要素は <p>囲まれないこともある
    ただし例外として、注釈における ol では、必ず<p>で囲まれる
     

  • <li>の中はほとんど地のページと同じで、多様な「文章以外の要素」が許容される。

    • ただし、上述したように、地のページでは文章要素が<p>で囲まれるが、<li>内部の疑似的なページでは文章要素に対するタグ囲みはない
       
  • message や details もある種の疑似的なページをつくる要素とみなせるが、これらは地のページと同じく文章要素は<p>で囲まれる

    • 引用も同様の性質を持つ
    • なので、<li>のみ『平文に対する<p>が無い』という特殊性を持つといえる

要するに

  1. <p>の中に出てくるもの:<img><br>・その他のタグと平文

    • img:image block に分離する必要がある
    • br:\nに(後で?)差し替える or paragraph block を追加するなどの処理が必要
    • それ以外:block を分離する必要はない
       
  2. <p>の中の要素」と「それ以外の<table><ul>などの要素」は

    • 地のページおよびその準拠の要素の中では、同じ階層では並ばない
    • <li>の中では、同じ階層で並ぶ
    • ただし、脚注の<li>は、<li><p>...なので、<p>と同じ性質を持つ
      (つまり「それ以外の要素」は存在せず、<img>は存在しうる)
       
  3. 上記より、パースでは、「<p>の中と脚注の<li><p>の中のパース」・「地のページおよびその準拠の要素の中のパース」・「<li>の中のパース」の3種が必要

nikogolinikogoli

「正解」であることをどのようにして判断するべきか

雑に考えれば「html の記述が多い ≒ 並列要素数が多い」ところが記事部分とは言えるが...

以前考えてたのは、今現在ユーザーが見ている (≒ 処理が呼び出された瞬間のマウスの位置に存在する or スクロール位置で判断する?) 要素が含まれていれば... ってやつ。