auto link title 解析微信公众号标题失败?

auto link title除了微信公众号基本都能成功提取标题,看console好像是跨域访问的问题。有没有其他类似的插件可以成功访问微信公众号呢?

(目前很折腾的方案是自己简单python写个request然后用text format插件通过api来调用,自行解析网址标题)

同样的问题,现在解析知乎标题也失败了

也许以前有跨域问题, 但目前 (2024-06) 觉得跟跨域没啥关系

对两个插件和两个网站分别讨论:

zolrath/obsidian-auto-link-title 楼上提到的插件
nekoshita/obsidian-auto-card-link 展现为卡片形式, 原理差不多

首先把 Auto Link Title 调整为不使用 “Use New Scraper”, 这样它会启动一个 Electron? BrowserWindow() 实例去访问网页, 能做的事多些

我自己测试是这样的:

Auto Link Title Auto Card Link
微信公众号 无法识别标题 正常
知乎单个问答 返回乱码标题 无法识别 Card
知乎单个专栏文章 正常 无法识别 Card

(如果大家测试跟我不一样, 那也有可能)


微信公众号的场景:

在无登录, 无 Cookie, 无 Referer 情况下, 直接访问微信公众号文章 url, 获取的 HTML 里, 没有 <title>文章真实标题</title> 但会显示一个

......
<meta property="og:title" content="文章真实标题" />
......

Auto Link Title 只找了 <title> 于是挂了
Auto Card Link 除了找 <title> 也找这个 "og:title", 因此能识别


知乎的场景:

估计就是最近增加反爬给搞的… 页面全都是加密脚本…

但问答和专栏的加密还不太一样,
单篇专栏文章的保护轻一些, Auto Link Title 是模仿浏览器去访问的, 还能拿到真实标题
看这意思, 专栏文章是漏网之鱼, 估计以后会给全都保护了


解决办法?

直接从浏览器复制为 [title](url) 得了,
有一堆浏览器插件方便干这个事, 比如 Copycat 等等

楼上说的对,auto-link-title通过linkpreview api、js request、模拟浏览器三种方式获取页面标题。但是微信公众号的网页metadata就是乱写,没有特定的parser解析根本获取不到准确的标题,知乎限制爬取之后必须带上cookie才能访问(gtihub上一堆issue都是关于这个的)

之前提过PR,为auto-link-title添加指定站点的cookie的功能,但是作者没动静。

迂回的方式就是从浏览器复制,我目前用油猴脚本实现在网页中按个快捷键就能获取md链接并完成md语法转义,代码如下:

// ==UserScript==
// @name         Alt+K 获取网页 Markdown 链接
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Create and copy a Markdown link from webpage title and URL using Alt + K shortcut, with syntax escaping
// @author       Grok AI
// @match        *://*/*
// @grant        GM_setClipboard
// ==/UserScript==

// 消息提示类,模仿 this.$message 效果
class Message {
    constructor() {
        this.container = document.createElement('div');
        this.container.id = 'messageContainer';
        this.container.style.cssText = `
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 9999;
            pointer-events: none; // 防止点击干扰
        `;
        document.body.appendChild(this.container);
    }

    show(message, iconType) {
        const p = document.createElement('p');
        p.style.cssText = `
            margin: 10px;
            padding: 10px;
            background-color: #f5f5f5;
            border-radius: 4px;
            display: flex;
            font-size:14px;
            align-items: center;
            color: #000000;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1); // 添加阴影
        `;
        const icon = document.createElement('span');
        icon.style.cssText = `
            width: 16px;
            height: 16px;
            background-color: green;
            border-radius: 50%;
            margin-right: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
        `;
        if (iconType === 'tick') {
            icon.innerHTML = '<svg viewBox="0 0 24 24" width="16" height="16"><path d="M9 16.2l-3.6-3.6c-.8-.8-.8-2 0-2.8s2-.8 2.8 0L9 11.6l6.2-6.2c.8-.8 2-.8 2.8 0s.8 2 0 2.8L11.8 16.2c-.4.4-.8.6-1.3.6-.5 0-.9-.2-1.3-.6z" fill="white"></path></svg>';
        }
        p.appendChild(icon);
        p.appendChild(document.createTextNode(message));
        this.container.appendChild(p);

        // 3 秒后移除提示
        setTimeout(() => {
            this.container.removeChild(p);
        }, 3000);
    }
}

// 主脚本
(function() {
    'use strict';

    // Markdown 特殊字符转义函数
    function escapeMarkdown(text) {
        if (!text) return 'Untitled'; // 防止空标题
        const specialChars = {
            '[': '\\[',
            ']': '\\]',
            '(': '\\(',
            ')': '\\)',
            '\\': '\\\\', // 转义反斜杠本身
            '*': '\\*', // 避免粗体解析
            '_': '\\_', // 避免斜体解析
            '#': '\\#', // 避免标题解析
            '`': '\\`' // 避免代码块解析
        };
        return text.replace(/[[\](){}\*#_`\\]/g, char => specialChars[char] || char);
    }

    // 监听快捷键 (Alt + K)
    document.addEventListener('keydown', function(event) {
        if (event.altKey && event.key === 'k') {
            event.preventDefault(); // 防止默认行为

            try {
                // 获取标题和链接
                const title = escapeMarkdown(document.title);
                const link = window.location.href;
                const markdownLink = `[${title}](${link})`;

                // 复制到剪贴板
                GM_setClipboard(markdownLink, 'text');

                // 显示成功提示
                const message = new Message();
                message.show(`已复制: ${markdownLink.substring(0, 50)}${markdownLink.length > 50 ? '...' : ''}`, 'tick');

                // 记录日志
                console.log(`Copied Markdown link: ${markdownLink}`);
            } catch (error) {
                console.error('Error generating Markdown link:', error);
                const message = new Message();
                message.show('生成链接失败,请检查页面内容', 'tick'); // 错误提示
            }
        }
    });

    // 页面加载完成提示
    window.addEventListener('load', function() {
        console.log('Markdown Link Creator is active. Use Alt + K to copy the link.');
    });
})();

1 个赞