feat(pugongying): 支持小红书短链接输入
通过 GM_xmlhttpRequest HEAD 请求跟踪短链接重定向, 从 finalUrl 中提取达人 ID。支持 xhslink.com 域名。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
465e1f7746
commit
99d16f1f70
@ -6,6 +6,7 @@
|
||||
// @match https://pgy.xiaohongshu.com/*
|
||||
// @grant GM_xmlhttpRequest
|
||||
// @connect api.internal.intelligrow.cn
|
||||
// @connect xhslink.com
|
||||
// @require https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js
|
||||
// ==/UserScript==
|
||||
|
||||
@ -235,27 +236,28 @@
|
||||
return baseTarget;
|
||||
}
|
||||
|
||||
function extractBloggerId(value) {
|
||||
const raw = normalizeScalar(value);
|
||||
if (!raw) {
|
||||
return "";
|
||||
}
|
||||
function resolveShortUrl(url) {
|
||||
return new Promise((resolve) => {
|
||||
if (typeof GM_xmlhttpRequest !== "function") {
|
||||
resolve(url);
|
||||
return;
|
||||
}
|
||||
GM_xmlhttpRequest({
|
||||
method: "HEAD",
|
||||
url,
|
||||
onload(res) {
|
||||
resolve(res.finalUrl || url);
|
||||
},
|
||||
onerror() {
|
||||
resolve(url);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (/^[0-9a-f]{24}$/i.test(raw)) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
if (!/^https?:\/\//i.test(raw)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(raw);
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
const SHORT_LINK_HOSTS = ["xhslink.com"];
|
||||
|
||||
function extractIdFromUrl(parsedUrl) {
|
||||
const queryCandidates = ["id", "user_id", "userId", "bloggerId", "creatorId"];
|
||||
for (const key of queryCandidates) {
|
||||
const queryValue = parsedUrl.searchParams.get(key);
|
||||
@ -279,7 +281,45 @@
|
||||
return "";
|
||||
}
|
||||
|
||||
function parseCreatorInputs(rawInput) {
|
||||
async function extractBloggerId(value) {
|
||||
const raw = normalizeScalar(value);
|
||||
if (!raw) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (/^[0-9a-f]{24}$/i.test(raw)) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
if (!/^https?:\/\//i.test(raw)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(raw);
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const directId = extractIdFromUrl(parsedUrl);
|
||||
if (directId) {
|
||||
return directId;
|
||||
}
|
||||
|
||||
if (SHORT_LINK_HOSTS.some((h) => parsedUrl.hostname.endsWith(h))) {
|
||||
const realUrl = await resolveShortUrl(raw);
|
||||
try {
|
||||
return extractIdFromUrl(new URL(realUrl));
|
||||
} catch (error) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
async function parseCreatorInputs(rawInput) {
|
||||
const values = normalizeScalar(rawInput)
|
||||
.split(/[\n,,\s]+/)
|
||||
.map((item) => item.trim())
|
||||
@ -288,8 +328,8 @@
|
||||
const ids = [];
|
||||
const seen = new Set();
|
||||
|
||||
for (const value of values) {
|
||||
const id = extractBloggerId(value);
|
||||
const resolved = await Promise.all(values.map((v) => extractBloggerId(v)));
|
||||
for (const id of resolved) {
|
||||
if (!id || seen.has(id)) {
|
||||
continue;
|
||||
}
|
||||
@ -508,7 +548,7 @@
|
||||
|
||||
return {
|
||||
async preview(rawInput, onProgress) {
|
||||
const ids = parseCreatorInputs(rawInput);
|
||||
const ids = await parseCreatorInputs(rawInput);
|
||||
if (!ids.length) {
|
||||
throw new Error("请输入至少一个有效的达人主页链接或达人 ID。");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user