pub const JS: &str = r#"(() => {
const loginWall = /登录后查看|请登录|登录后/.test(document.body.innerText);
const notFound = /用户不存在|页面不见了/.test(document.body.innerText);
if (loginWall) return { loginWall: true, notFound: false, media: [] };
if (notFound) return { loginWall: false, notFound: true, media: [] };
const mediaSet = new Set();
const media = [];
function addMedia(type, url) {
if (!url || mediaSet.has(url)) return;
mediaSet.add(url);
media.push({ type, url });
}
// Method 1: __INITIAL_STATE__.note.noteDetailMap
const state = window.__INITIAL_STATE__;
if (state && state.note && state.note.noteDetailMap) {
const map = state.note.noteDetailMap;
const keys = Object.keys(map);
for (const key of keys) {
const detail = map[key];
const note = (detail && detail.note) ? detail.note : detail;
if (!note) continue;
// Video extraction
if (note.video) {
const v = note.video;
let videoUrl = null;
if (v.media && v.media.stream) {
const stream = v.media.stream;
const h264 = stream.h264 || stream.H264;
if (Array.isArray(h264) && h264.length > 0) {
videoUrl = h264[0].masterUrl || h264[0].url || null;
}
}
if (!videoUrl && v.media && v.media.originVideoKey) {
videoUrl = 'https://sns-video-bd.xhscdn.com/' + v.media.originVideoKey;
}
if (!videoUrl && v.url) {
videoUrl = v.url;
}
if (videoUrl) addMedia('video', videoUrl);
}
// Image extraction
if (note.imageList && Array.isArray(note.imageList)) {
for (const img of note.imageList) {
let imgUrl = null;
if (img.infoList && Array.isArray(img.infoList) && img.infoList.length > 0) {
// Pick best resolution (last entry tends to be highest)
const best = img.infoList[img.infoList.length - 1];
imgUrl = best.url || null;
}
if (!imgUrl) imgUrl = img.urlDefault || img.url || null;
if (imgUrl) addMedia('image', imgUrl);
}
}
}
}
// Method 2: Inline <script> tags regex for video URLs
if (media.filter(m => m.type === 'video').length === 0) {
const scripts = document.querySelectorAll('script:not([src])');
const videoRe = /(https?:\/\/(?:sns-video[^"' ]*\.mp4|[^"' ]*xhscdn[^"' ]*\.mp4))/g;
for (const script of scripts) {
let match;
while ((match = videoRe.exec(script.textContent)) !== null) {
addMedia('video', match[1]);
}
}
}
// Method 3: DOM <video> elements
if (media.filter(m => m.type === 'video').length === 0) {
const videos = document.querySelectorAll('video[src], video source[src]');
for (const el of videos) {
const src = el.src || el.getAttribute('src');
if (src && !src.startsWith('blob:')) addMedia('video', src);
}
}
// Method 4: DOM <img> matching XHS CDN patterns
if (media.filter(m => m.type === 'image').length === 0) {
const imgs = document.querySelectorAll('img[src]');
for (const img of imgs) {
const src = img.src || img.getAttribute('src');
if (src && (src.includes('ci.xiaohongshu.com') || src.includes('xhscdn'))) {
addMedia('image', src);
}
}
}
return { loginWall: false, notFound: false, media };
})()"#;