惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
IT之家
IT之家
C
Check Point Blog
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
H
Hackread – Cybersecurity News, Data Breaches, AI and More
美团技术团队
M
MIT News - Artificial intelligence
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Security Blog
Microsoft Security Blog
G
Google Developers Blog
F
Fortinet All Blogs
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
Hugging Face - Blog
Hugging Face - Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
The Cloudflare Blog
博客园 - 三生石上(FineUI控件)

摸鱼论坛 - 最新帖子

友情链接改一下地址吧 域名换了 - 摸鱼论坛 ahtajc 一口价域名 - 摸鱼论坛 上传图片有问题 - 摸鱼论坛 《陈翔六点半》“妹爷”扮演者去世,终年82岁。 - 摸鱼论坛 .ai和.com - 摸鱼论坛 30岁以后开始断社交了 - 摸鱼论坛 【重磅公告】资费彻底告急,正式宣布雷若论坛即将永久关. - 摸鱼论坛 自托管社交内容发布平台 - 摸鱼论坛 导航网站增加收录功能,留下网址,可以自动申请收录 - 摸鱼论坛 真正 免费邮箱,无任何利益需求 - 摸鱼论坛 书签最新版来了,全站弹窗风格统一,用户体验一致 - 摸鱼论坛 限时免费使用 GPT-5.4 和 Sonnet 4.6(不限次数) - 摸鱼论坛 我也写了两个版本的朋友圈程序。 - 摸鱼论坛 科普 - 聚域一口价域名交易和域名抢注服务平台 - 摸鱼论坛 面试了一家大手日企 - 摸鱼论坛 分享 如何批量获取商家联系方式 - 摸鱼论坛 站长公益主机 APP 下打包好了 - 摸鱼论坛 AI分享论坛搭建好了 - 摸鱼论坛 搞到1点了,搭建一个在线聊天室,功能更加流畅 - 摸鱼论坛 域名金牌会员到底值不值? - 摸鱼论坛 腾讯即将推出腾讯网盘,官网已上线 - 摸鱼论坛 一个企业级通讯工具TWT Link - 摸鱼论坛 如果不急着购买域名,可以一口价蹲 - 摸鱼论坛 来个导航站点,帮我收录一下(beeimg.cn) - 摸鱼论坛 聚域网免费whois域名查询工具 - 摸鱼论坛 (调查问卷)本站程序的发行方式。 - 摸鱼论坛 NodeSuper - 数字世界的灯塔,互联网爱好者的家园! - 摸鱼论坛 MiMoCode用 MiMo-V2.5(包含 gml5.1、ds4pro 等)限免中 - 摸鱼论坛 Typora激活劫持(破解) 支持到1.13.7 - 摸鱼论坛 1vps.cn(壹云)适用于挂机宝、云服务器等。明盘888拿下 - 摸鱼论坛
一个日语长文标音项目(PHP) - 摸鱼论坛
cc · 2026-06-06 · via 摸鱼论坛 - 最新帖子

在这里备份一下,基于mecab和unidic。
可以把汉字翻译成平假名,把外来语翻译成片假名。
之前做的,后面发现对自己学日语没啥用,项目就停掉了。

<?php
// apt install mecab unidic-mecab
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    try {
        $process = proc_open('mecab', [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes);
        if (is_resource($process)) {
            fwrite($pipes[0], file_get_contents('php://input'));
            fclose($pipes[0]);
            $result = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            $error = stream_get_contents($pipes[2]);
            fclose($pipes[2]);
            proc_close($process);
            if (!empty($error)) { throw new Exception($error); }
            http_response_code(200);
            echo $result;
        } else { throw new Exception('Failed to open process'); }
    } catch (Exception $e) {
        http_response_code(500);
        echo $e;
    }
    exit;
}
?>

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="data:," />
    <title>JPhonetic - MeCab + UniDic</title>
</head>

<body>
    <textarea id="inputText" style="display:block;width:600px;max-width:calc(100% - 4px);height:200px;"></textarea>
    <input type="button"
        onclick="notation(document.querySelector('#inputText').value, document.querySelector('#text'));" value="注音" />
    <input type="file" id="fileInput" /><br /><br />
    <div id="text"></div>
    <script>
        function hiragana(str) {
            return str.replace(/[\u30A1-\u30F6]/g, ch => String.fromCharCode(ch.charCodeAt(0) - 0x60));
        }
        function notation(text, dom) {
            if (!text) { return; }
            fetch('', {
                method: 'POST',
                headers: { 'Content-Type': 'text/plain' },
                body: text
            })
                .then(response => response.text())
                .then(data => {
                    let result = '';
                    data.split(/\r?\n/).map((row) => {
                        const values = row.split('\t');
                        if (values.length <= 1) { return; }
                        const word = values[0];
                        const part = values[1].split(/,(?=(?:["]*"["]*")*[^"]*$)/);
                        const yomi = part[20] ?? '';
                        if (/[\u4E00-\u9FFF\u3400-\u4DBF]/.test(word) && yomi) {
                            result += " " + word + "[" + hiragana(yomi) + "] ";
                        } else if (/^[\u30A0-\u30FF]+$/.test(word) && part[7]?.split('-')[1]) {
                            result += " " + word + "[" + part[7]?.split('-')[1] + "] ";
                        } else if (/^[A-Za-z0-9\p{P}]+$/u.test(word)) {
                            result += " " + word + " ";
                        } else {
                            result += word;
                        }
                    });
                    dom.innerHTML = result;
                })
                .catch(error => {
                    console.error('Error:', error);
                });
        }
        document.getElementById("fileInput").addEventListener("change", async function () {
            const file = this.files[0];
            if (!file) return;
            const formData = new FormData();
            formData.append("file", file);
            formData.append("url", "");
            formData.append("language", "auto");
            formData.append("isOverlayRequired", "true");
            formData.append("FileType", ".Auto");
            formData.append("IsCreateSearchablePDF", "false");
            formData.append("isSearchablePdfHideTextLayer", "true");
            formData.append("detectOrientation", "false");
            formData.append("isTable", "false");
            formData.append("scale", "true");
            formData.append("OCREngine", "3");
            formData.append("detectCheckbox", "false");
            formData.append("checkboxTemplate", "0");
            document.querySelector("#text").innerHTML = '<span style="color: blue;">Loading...</span>';
            try {
                const res = await fetch("https://api8.ocr.space/parse/image", {
                    method: "POST",
                    headers: {
                        "accept": "application/json, text/javascript, */*; q=0.01",
                        "apikey": "donotstealthiskey_ip1",
                        "origin": "https://ocr.space",
                        "referer": "https://ocr.space/",
                    },
                    body: formData
                });
                const json = await res.json();
                if (json?.ParsedResults?.[0]?.ParsedText) {
                    notation(json?.ParsedResults?.[0]?.ParsedText, document.querySelector("#text"));
                } else {
                    document.querySelector("#text").innerHTML = '<span style="color:red;">' + JSON.stringify(json) + '</span>';
                }
            } catch (error) {
                document.querySelector("#text").innerHTML = '<span style="color:red;">' + error.message + '</span>';
            }
        });
    </script>
</body>

</html>

你好呀,陌生人

看起来你是新来的,如果想参与讨论,可以先登录或注册。

Statistics

注册会员: 284
主题: 541
回复: 1588

New Members

友情链接