แคปหน้าจอเว็บทีละหลายโดเมน + บังคับให้ชนเซิร์ฟเวอร์ต้นทาง ข้าม Cloudflare
เวลาต้องตรวจว่าเซิร์ฟเวอร์ต้นทาง render ถูกจริง ไม่ใช่ดูของที่ CDN cache ไว้ ต้องบังคับให้เบราว์เซอร์ต่อตรงไป IP ต้นทาง — แต่วิธีแก้ hosts บน Windows มักโดนแอนติไวรัสคืนค่า ทางที่นิ่งกว่าคือ override DNS ในตัวเบราว์เซอร์เอง
พอดีผมต้องแคปหน้าจอเว็บทีละหลายโดเมนบ่อย — ทั้งไล่ตรวจงานหลังย้ายเซิร์ฟเวอร์ว่าทุกไซต์ยังขึ้นถูก และตอนอยาก audit ว่า "เซิร์ฟเวอร์ต้นทาง" render ถูกจริง ไม่ใช่ดูของที่ Cloudflare cache ค้างไว้ ตอนแรกใช้วิธีเดิม ๆ แล้วเจอกำแพงสองอัน เลยเปลี่ยนมาใช้ Playwright ซึ่งจบทั้งคู่ เอามาเล่าไว้
กำแพงที่ 1: flag screenshot ของ Chrome พัง
วิธีคลาสสิกคือสั่ง chrome --headless --screenshot แต่ตั้งแต่ Chrome 132 เป็นต้นมา flag นี้พังกับโหมด headless ใหม่ (--headless=new ไม่รองรับ --screenshot) จะได้ไฟล์เปล่าหรือ error
มันเปลี่ยนพฤติกรรมตามเวอร์ชัน Chrome จนเชื่อถือไม่ได้ — ใช้ Playwright/CDP ที่คุมผ่านโปรโตคอลแทน เสถียรข้ามเวอร์ชันกว่ามาก
กำแพงที่ 2: อยากชนต้นทาง แต่แก้ hosts โดน AV คืนค่า
ถ้าจะบังคับให้โดเมนชี้ไป IP ต้นทาง (ข้าม Cloudflare) วิธีปกติคือแก้ไฟล์ hosts แต่บน Windows แอนติไวรัส (Kaspersky/Defender) มักมองว่าการแก้ hosts เป็นพฤติกรรมมัลแวร์ แล้วคืนค่ากลับทันที — แก้ไปก็ไม่อยู่
ทางออก: Playwright มี option override DNS ระดับโปรเซส (--host-resolver-rules) ที่ทำงานเฉพาะในเบราว์เซอร์ตัวที่รัน ไม่แตะไฟล์ระบบ AV เลยไม่เห็นและไม่คืนค่า
สคริปต์ที่ใช้
// shot.js — แคปทีละโดเมนจาก sites.txt, บังคับ origin IP ถ้าใส่ --origin
const { chromium } = require('playwright');
const fs = require('fs');
(async () => {
const args = process.argv.slice(2);
const oi = args.indexOf('--origin');
const originIP = oi >= 0 ? args[oi + 1] : null;
const listFile = args[args.length - 1];
const sites = fs.readFileSync(listFile, 'utf8').split('\n').map(s => s.trim()).filter(Boolean);
const launchArgs = [];
if (originIP) {
// ชี้ทุกโฮสต์ไป origin IP — เฉพาะโปรเซสนี้ ไม่แตะ hosts ระบบ
launchArgs.push(`--host-resolver-rules=MAP * ${originIP}`);
}
const browser = await chromium.launch({ args: launchArgs, ignoreHTTPSErrors: true });
for (const url of sites) {
const page = await browser.newPage({ viewport: { width: 1366, height: 900 }, ignoreHTTPSErrors: true });
try {
await page.goto(url.startsWith('http') ? url : 'https://' + url,
{ waitUntil: 'networkidle', timeout: 30000 });
const name = url.replace(/[^a-z0-9]/gi, '_') + '.png';
await page.screenshot({ path: 'shots/' + name, fullPage: false });
console.log('[OK] ' + url);
} catch (e) {
console.log('[ERR] ' + url + ' — ' + e.message);
}
await page.close();
}
await browser.close();
})();
mkdir -p shots
# แคปตามปกติ (ผ่าน Cloudflare)
node shot.js sites.txt
# บังคับชนต้นทาง (ข้าม CDN) — เห็นสิ่งที่ origin เสิร์ฟจริง
node shot.js --origin 203.0.113.10 sites.txt
ตอนย้ายเซิร์ฟเวอร์หรือไล่ตรวจ ต้องรู้ว่า "เครื่องใหม่ต้นทาง" render ถูกไหม ก่อนจะสลับ DNS จริง — MAP * origin_ip ทำให้เบราว์เซอร์ต่อตรงไปเครื่องใหม่โดยไม่ต้องแตะ DNS สาธารณะ เห็นของจริงก่อน cutover
ข้อควรระวัง
- ignoreHTTPSErrors ต้องเปิดตอนชน origin IP เพราะ cert ปลายทางอาจยังไม่ตรงชื่อโดเมน (เครื่องใหม่ที่ยังไม่ออก cert) — ไม่งั้นจะ error ก่อนโหลด
- networkidle ช่วยให้หน้าโหลดเสร็จก่อนแคป แต่บางเว็บที่ยิง request ตลอดจะ timeout — เปลี่ยนเป็น
domcontentloaded+waitForTimeoutถ้าเจอ - แคปเยอะ ๆ เปิดทีละ page แล้วปิด อย่าเปิดค้างพร้อมกันหมด เดี๋ยว RAM บาน
สรุปคือปัญหาการแคปหน้าจอจำนวนมากไม่ได้อยู่ที่ตัวเบราว์เซอร์ แต่อยู่ที่เครื่องมือเดิม (chrome flag ที่พัง, hosts ที่ AV คืนค่า) — พอย้ายมาคุมผ่าน Playwright ทั้ง override DNS ระดับโปรเซสและการแคปก็นิ่งข้ามเวอร์ชัน โดยเฉพาะการยืนยัน origin ก่อน cutover ที่ทำได้โดยไม่ต้องแตะ DNS สาธารณะ ใครทำงาน migration หรือ audit เว็บหลายไซต์เอาไปปรับใช้ได้ตามสะดวกครับ ตรงไหนผมอธิบายตกหล่นหรือพิมพ์ผิด เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ
อยากให้เราทำให้ไหม?
ให้เราช่วยติดตั้ง ตั้งค่า ย้ายระบบ หรือแก้ปัญหาเซิร์ฟเวอร์ เพื่อให้คุณมีเวลาไปทำงานที่สำคัญกว่า
เคยเจองานแบบนี้ไหม? ติดตรงไหน?
มาแลกวิธีกันต่อในบอร์ด LinuxThai



ความคิดเห็น 0
ยังไม่มีความคิดเห็น — เป็นคนแรกเลย