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/*
|
// @match https://pgy.xiaohongshu.com/*
|
||||||
// @grant GM_xmlhttpRequest
|
// @grant GM_xmlhttpRequest
|
||||||
// @connect api.internal.intelligrow.cn
|
// @connect api.internal.intelligrow.cn
|
||||||
|
// @connect xhslink.com
|
||||||
// @require https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js
|
// @require https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
|
||||||
@ -235,27 +236,28 @@
|
|||||||
return baseTarget;
|
return baseTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractBloggerId(value) {
|
function resolveShortUrl(url) {
|
||||||
const raw = normalizeScalar(value);
|
return new Promise((resolve) => {
|
||||||
if (!raw) {
|
if (typeof GM_xmlhttpRequest !== "function") {
|
||||||
return "";
|
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)) {
|
const SHORT_LINK_HOSTS = ["xhslink.com"];
|
||||||
return raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^https?:\/\//i.test(raw)) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
let parsedUrl;
|
|
||||||
try {
|
|
||||||
parsedUrl = new URL(raw);
|
|
||||||
} catch (error) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function extractIdFromUrl(parsedUrl) {
|
||||||
const queryCandidates = ["id", "user_id", "userId", "bloggerId", "creatorId"];
|
const queryCandidates = ["id", "user_id", "userId", "bloggerId", "creatorId"];
|
||||||
for (const key of queryCandidates) {
|
for (const key of queryCandidates) {
|
||||||
const queryValue = parsedUrl.searchParams.get(key);
|
const queryValue = parsedUrl.searchParams.get(key);
|
||||||
@ -279,7 +281,45 @@
|
|||||||
return "";
|
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)
|
const values = normalizeScalar(rawInput)
|
||||||
.split(/[\n,,\s]+/)
|
.split(/[\n,,\s]+/)
|
||||||
.map((item) => item.trim())
|
.map((item) => item.trim())
|
||||||
@ -288,8 +328,8 @@
|
|||||||
const ids = [];
|
const ids = [];
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
|
|
||||||
for (const value of values) {
|
const resolved = await Promise.all(values.map((v) => extractBloggerId(v)));
|
||||||
const id = extractBloggerId(value);
|
for (const id of resolved) {
|
||||||
if (!id || seen.has(id)) {
|
if (!id || seen.has(id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -508,7 +548,7 @@
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
async preview(rawInput, onProgress) {
|
async preview(rawInput, onProgress) {
|
||||||
const ids = parseCreatorInputs(rawInput);
|
const ids = await parseCreatorInputs(rawInput);
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
throw new Error("请输入至少一个有效的达人主页链接或达人 ID。");
|
throw new Error("请输入至少一个有效的达人主页链接或达人 ID。");
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user