import { chromium } from 'rebrowser-playwright'; import { readFileSync } from 'node:fs'; const COOKIE_FILE = `${process.env.HOME}/.social-mcp/xiaohongshu/cookies.json`; async function main() { const raw = JSON.parse(readFileSync(COOKIE_FILE, 'utf-8')); const browser = await chromium.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu'] }); const ctx = await browser.newContext({ storageState: raw }); const page = await ctx.newPage(); console.log('Visiting main site...'); await page.goto('https://www.xiaohongshu.com/explore', { waitUntil: 'domcontentloaded' }); await page.waitForTimeout(2000); // Find creator center link on the main site const creatorLinks = await page.$$eval('a[href*="creator"]', els => els.map(el => ({ href: el.getAttribute('href'), text: el.textContent?.trim() })).slice(0, 5) ); console.log('Creator links on main site:', creatorLinks); // The creator link opens in a new tab — capture it const [creatorPage] = await Promise.all([ ctx.waitForEvent('page'), page.click('a[href*="creator.xiaohongshu.com/publish"]'), ]); await creatorPage.waitForLoadState('domcontentloaded'); await creatorPage.waitForTimeout(3000); console.log('\nCreator page URL:', creatorPage.url()); console.log('Creator page title:', await creatorPage.title()); console.log('Title:', await page.title()); console.log('URL:', page.url()); const pg = creatorPage; // Switch to image tab — skip off-screen duplicate const switched = await pg.$$eval('.creator-tab', (tabs) => { for (const tab of tabs) { if (!tab.textContent?.includes('图文')) continue; const style = (tab as HTMLElement).style; if (style.left && parseInt(style.left) < -100) continue; const rect = tab.getBoundingClientRect(); if (rect.width === 0 && rect.height === 0) continue; (tab as HTMLElement).click(); return true; } return false; }); console.log('Switched to image tab:', switched); await pg.waitForTimeout(1000); // Set the file on the hidden input const fileInput = await pg.waitForSelector('input[type="file"]', { state: 'attached', timeout: 10000 }); console.log('File input found, setting file...'); await fileInput.setInputFiles('/Users/xd/Downloads/IMG_1479.png'); console.log('File set. Waiting 5s for upload...'); await pg.waitForTimeout(5000); // Check what appeared after upload const allImgEls = await pg.$$eval('img', els => els.filter(el => el.src && !el.src.startsWith('data:') && el.offsetParent !== null) .map(el => ({ src: el.src.slice(0, 80), cls: el.className })) ); console.log('\nVisible imgs after upload:', allImgEls); // Check fixed selector const imgContainers = await pg.$$('.img-upload-area .img-container'); console.log('\n.img-upload-area .img-container count:', imgContainers.length); // Verify updated selectors const imgContainerCount = await pg.$$('.img-upload-area .img-container').then(els => els.length); console.log('\n[selector check] .img-upload-area .img-container:', imgContainerCount); const titleInput = await pg.$('input.d-text[placeholder*="标题"]'); console.log('[selector check] title input:', !!titleInput); const contentEditor = await pg.$('.tiptap.ProseMirror'); console.log('[selector check] content editor:', !!contentEditor); const publishBtn = await pg.$('button.d-button:has-text("发布")'); console.log('[selector check] publish button:', !!publishBtn, publishBtn ? await publishBtn.textContent() : ''); await browser.close(); } main().catch(e => { console.error(e); process.exit(1); });