Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
OSSコミットしてZennの課題を解決した話
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
dyoshikawa
July 21, 2024
Technology
680
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
OSSコミットしてZennの課題を解決した話
dyoshikawa
July 21, 2024
More Decks by dyoshikawa
See All by dyoshikawa
エンジニア向けコミュニティZennの開発チームを支える自動化の仕組み.pdf
dyoshikawa1993
0
2.6k
生PHPで学ぶSSRF.pdf
dyoshikawa1993
0
180
Zennへのスパム投稿が急増したのでLLMでなんとかした話
dyoshikawa1993
0
1.4k
Google Cloud Vertex AIにおけるGemini vs Claude
dyoshikawa1993
0
240
Other Decks in Technology
See All in Technology
日本 Fintech 未来予測レポート 2027〜2028年(手動編集版)
8maki
0
2.3k
自律型AIエージェントは何を破壊するのか
kojira
0
160
2026TECHFRESH畢業分享會 - Lightning Talk - 資料也要 CI/CD? 用 Airbyte 自動化資料同步
line_developers_tw
PRO
0
1.1k
2026TECHFRESH畢業分享會 - AI 時代的人生存檔點
line_developers_tw
PRO
0
1.1k
Socrates × Looker 〜セマンティックレイヤーで進化するデータ分析エージェント〜
hanon52_
3
2.4k
2026TECHFRESH畢業分享會 - 原生還是跨平台? App 開發踩坑實錄
line_developers_tw
PRO
0
1.1k
自宅LLMの話
jacopen
1
600
フィジカル版Github Onshapeの紹介
shiba_8ro
0
260
2026年6月23日 Syncable Tech + Start Python Club にて
hamukazu
0
120
気軽に使える"情報のハブ"としてのNotion活用 〜フロー情報の集積点 と、 Claude Code × Notion AI〜
syucream
1
140
Android の公式 Skill / Android skills
yanzm
0
150
Bedrock AgentCore RuntimeでAuth0 Changelog調査AIをアップグレードした話
t5u8a5a
1
160
Featured
See All Featured
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
390
A designer walks into a library…
pauljervisheath
211
24k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
610
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
850
Unsuck your backbone
ammeep
672
58k
We Are The Robots
honzajavorek
0
250
Everyday Curiosity
cassininazir
0
230
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
840
What's in a price? How to price your products and services
michaelherold
247
13k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
410
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
620
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Transcript
OSSコミットして Zennの課題を解決した話 2024.7.18 新規事業部Zennチーム dyoshikawa
2020年10月入社(今年で4年目) 2023年よりZennチーム バックエンドエンジニア ZennではRuby on Rails開発 Webフロントエンド(React|Next)も触ります 自己紹介
https://zenn.dev/ エンジニアのための情報共有コミュニティサービス 2023年12月に会員数10万|月間PV数1000万突破を発表 🎉 Zennについて
Zennではopen-graph-scraperというnpmパッケージを使っています https://github.com/jshemas/openGraphScraper Open Graph(OG)情報の読み取りを良い感じにやってくれる Open Graph protocol 今回はこのopen-graph-scraperの話 OGの読み取りにopen-graph-scraperを使用
リンクカードに使用 記事執筆でURLだけが記述された行があると、その部分がリンクカ ードとして表示される仕様 ➡️ OGの読み取りにopen-graph-scraperを使用
使い方の例 import ogs from "open-graph-scraper"; (async () => { const
data = await ogs({ url: "https://classmethod.jp/", }); console.log(JSON.stringify(data.result, null, 2)); })(); OGの読み取りにopen-graph-scraperを使用
クラスメソッドコーポレートサイトを読み取るとこんな感じ https://classmethod.jp/ { "success": true, "ogLocale": "ja_JP", "ogSiteName": "クラスメソッド株式会社", "ogType":
"article", "ogTitle": "クラスメソッド株式会社", "ogDescription": "クラスメソッドはクラウド、デジタル化、データの3つの分野を掛けあわせて、お客様のビジネス成長に向けた技術支援を行います。2022年に "以下省略": "..." } OGの読み取りにopen-graph-scraperを使用
v5.2.0より文字コードごとのデコード処理がなくなり、アップデート するとUTF-8でないサイトで問題が発生するようになった Shift_JISやEUC-JPなどのWebページをopen-graph-scraperで読み 取ると結果が文字化けしてしまう 課題: open-graph-scraperをアップデートできない
これによりバージョン5.2.0以前に固定する状態が続いていた パッケージの「塩漬け」が課題に 課題: open-graph-scraperをアップデートできない
同じ問題がopenGraphScraperリポジトリのIssueに起票されていた 課題: open-graph-scraperをアップデートできない
課題: open-graph-scraperをアップデートできない
Shift_JIS Webページの例として阿部寛のホームページが取り上げられ ている 本発表でも例として使わせていただきます 🙏 課題: open-graph-scraperをアップデートできない
阿部寛のホームページを読み取った場合 import ogs from "open-graph-scraper"; // v6.3.4 (async () =>
{ const { result } = await ogs({ url: 'http://abehiroshi.la.coocan.jp/' }) console.log(JSON.stringify(result, null, 2)) })(); 以下の結果に { "ogTitle": "�������̃z�[���y�[�W", // "阿部寛のホームページ"を期待 "charset": "Shift_JIS", "requestUrl": "http://abehiroshi.la.coocan.jp/", "success": true } 課題: open-graph-scraperをアップデートできない
阿部寛のホームページ が �������̃z�[���y�[�W に文字化け なんかこう、うまくゴニョゴニョして �������̃z�[���y�[�W から復元 できたりしないものなの・・・? ここで文字化けがどのように起きるかをみてみる 文字化け部分を修復して使えないの?
最初の2文字 阿部 を例に まずはUTF-8の 阿部 をShift_JISとしてデコードするとどう文字化けす るか?をみる UTF-8の 阿部 のバイト列は
e998bfe983a8 阿 e998bf 部 e983a8 例1: UTF-8の文字列をShift_JISでデコードする場合
e998bfe983a8 をShift_JISでデコードすることを考える Shift_JISの定義表を見ながらバイト列を再解釈して文字を置換する JIS X 0208コード表 - CyberLibrarian 例1: UTF-8の文字列をShift_JISでデコードする場合
すると 阿部 は 髦ソ驛ィ になる これが文字化け! ➡️ 例1: UTF-8の文字列をShift_JISでデコードする場合 阿
e998bf 部 e983a8 UTF-8 髦 e998 ソ bf 驛 e983 ィ a8 Shift_JIS
e998bfe983a8 というバイト列はそのまま残っていることに注目 そのため、これをUTF-8に再度デコードすると 阿部 を復元できる ➡️ 髦ソ驛ィ は 阿部 に復元できる
髦 e998 ソ bf 驛 e983 ィ a8 Shift_JIS 阿 e998bf 部 e983a8 UTF-8
今度は逆にShift_JISからUTF-8にデコード 今回の問題はこっち Shift_JISの 阿部 はバイト列にすると 88a29594 になる 阿 88a2 部
9594 例2: Shift_JISの文字列をUTF-8でデコードする場合
88a29594 をUTF-8でデコードすることを考える ところが・・・?このバイト列に対してUTF-8の定義表から対応させ られる文字がない 例2: Shift_JISの文字列をUTF-8でデコードする場合
そういう場合はREPLACEMENT CHARACTER( � )の出番になる 実際手元で試すと 阿部 は ���� になった 88a29594
は4バイトなので、1バイト区切りで ���� になったと思 われる(デコーダの実装によりそう) ➡️ 例2: Shift_JISの文字列をUTF-8でデコードする場合 阿 88a2 部 9594 Shift_JIS � efbfbd � efbfbd � efbfbd � efbfbd UTF-8
バイト列が efbfbdefbfbdefbfbdefbfbd になってしまい、元の値 88a29594 を保持できていないことに注目 そのためREPLACEMENT CHARACTERに置換されてしまった場合は元 の文字列に戻すことは困難(おそらくできない) REPLACEMENT CHARACTERは復元が困難
🤔「 阿部寛のホームページ の文字化け後の �������̃z�[���y�[�W には � じゃない文字も含まれてるけど?」 ちなみに: 文字化けに �
でない文字がある件
Shift_JISにおいて 阿部寛のホームページ のバイト列は 88a295948ab082cc837a815b83808379815b8357 になる 一部UTF-8としてデコードできる文字がある ちなみに: 文字化けに � でない文字がある件
������� 88a295948ab082 ~ cc83 z 7a � 81 [ 5b �� 838083 y 79 � 81 [ 5b � 83 W 57 UTF-8
UTF-8での cc83 Unicodeでは U+0303 のチルダ ~ はCOMBINED TILDEといって、他の文字と組み合わせて使うものらしい REPLACEMENT CHARACTER
� と組み合わさって �̃ になる 発音表記などで使われる ちなみに: 文字化けに � でない文字がある件
話を戻して・・・ 解決するため、OSSコントリビューションすることに 解決策: OSSコントリビューションする
理由 自前で実装し直すよりライブラリにパッチを当てた方が工数がかか らない open-graph-scraperを使い続けることで、本OSSの今後のエンハン スの利益を受け続けることができる 他の非英語圏ユーザにも役に立つと思った 幸い、活発に開発が続いている状況だったので、プルリクエストが受 け入れられる可能性は高いと思った 解決策: OSSコントリビューションする
https://github.com/jshemas/openGraphScraper/pull/206 プルリクエストを作成
fetch() + text() の時点でUTF-8デコーディングが行われる response = await fetch(/* 省略 */);
body = await response.text(); text() の時点で文字化けが発生してしまうため、ここに手を入れ る必要がある text() は Response インターフェイスのメソッドで、 Response ストリームを取得して完全に読み込みます。 String で解決する プロミスを返します。 レスポンスは常に UTF-8 としてデコードされます。 https://developer.mozilla.org/ja/docs/Web/API/Response/text どんなPRを出したの?元コードの挙動
一応、ミニマムなコードで動作を確認してみる (async () => { const response = await fetch("http://abehiroshi.la.coocan.jp/");
const body = await response.text(); // 243文字目が<title />の中身の `�` にあたる console.log(body[243], dummy.charCodeAt(243).toString(16)); // � fffd })(); dummy.charCodeAt(243) の結果(Code Unit)が fffd であり、こ れはUTF-16における � のバイト列である Node.jsは内部的にUTF-16を採用している つまり、やはり元のバイト列は残っておらず復元は困難である どんなPRを出したの?元コードの挙動
text() ではなく arrayBuffer() を使うことでデコード前のバイト 列を取得し、 bodyArrayBuffer 変数で保持しておく bodyArrayBuffer を保持したままUTF-8デコードを行い、 <meta
charset="{charset}" /> を取得するなどして文字コードを特定する 特定した文字コードで bodyArrayBuffer をデコードする const bodyArrayBuffer = await response.arrayBuffer(); const bodyText = Buffer.from(bodyArrayBuffer).toString('utf-8'); const charset = getCharset(bodyText, bodyArrayBuffer, load(bodyText)); if (charset.toLowerCase() === 'utf-8') { body = bodyText; } else { body = decode(Buffer.from(bodyArrayBuffer), charset); } どんなPRを出したの?こう変更した
いろいろとやりとりや確認待ちもあり、2週間ほどかかったがマージさ れる ほどなくして本プルリクエストの変更内容を取り込んだv6.4.0もリリ ースされる 動作確認し文字化け問題が直っていることを確認 Zennにも最新版を適用しリリースできた 付き合っていただいたメンテナに感謝 🎉 結果: 無事マージされる
🎉
リンクカードの実装にはopen-graph-scraperを使うと楽 文字化けは復元できる場合と困難な場合がある 「OSSを乗り換える」 「OSSを使うのをやめる」の他に「OSSに貢献す る」の選択肢を持ってみると良さそう まとめ
本日のお話は下記にもう少し詳しく書いています OSSにコミットしてサービスの課題を解決した話 文字コード入門 文字化けはなぜ起こるのか?どういう時に復元できるのか? ブログ記事
筆者は文字コードや符号化方式の専門家ではないため、勉強しながら 本課題に取り組みました 理解が間違っている箇所があればご指摘ください 🙏 ここまでお聞きいただきありがとうございました さいごに
特殊用途文字 (Unicodeのブロック) - Wikipedia とほほの文字コード入門 - とほほのWWW入門 UTF-8 - Wikipedia
JIS X 0208コード表 - CyberLibrarian 文字列とUnicode · JavaScript Primer #jsprimer JavaScript における文字コードの初歩 - 30歳からのプログラミング (プログラマのための)いまさら聞けない標準規格の話 第2回 文字コー ド実践編 | オブジェクトの広場 参考
XML用語事典 [シフトJIS(Shift_JIS) ] Shift_JIS 文字コード表 特殊用途文字 (Unicodeのブロック) - Wikipedia 合成可能なダイアクリティカルマーク
- Wikipedia ability to validate UTF-8 encoding · Issue #83 · ashtuchkin/iconv-lite 参考