打开Chrome开发者工具F12翻了半小时才找到那段统计代码,换成wget递归下载再用grep扫一遍,30个站的所有JS文件5分钟全部提取完
做站群的都知道,有时候需要看看同行网站用了什么统计代码、广告代码、前端特效、甚至是反爬逻辑。打开F12,切到Sources面板,一个文件一个文件点开看——看一两个站还行,看20个站?每个站可能加载了十几个JS文件,合起来几百个文件,手动翻真的要疯。
更坑的是,很多JS代码是经过压缩混淆的,一行几千个字符,混在一堆代码里,肉眼根本找不出来你要的那段逻辑。你想找的是百度统计的代码,结果翻了5个文件全是jQuery和Lodash,正主在哪都不知道。
实际上,JS代码的批量采集有四种主流方法,从简单到复杂、从单站到批量,每种适合的场景完全不一样。选对了方法,几十个站的JS代码提取就是一条命令的事。

四种JS采集方式一图对比
| 方式 | 适合场景 | 单站耗时 | 批量能力 | 能拿到动态加载的JS吗 |
| F12手动复制 | 临时看1-2个站 | 10-30分钟 | 几乎没有 | 能 |
| wget/curl递归下载 | 批量扒静态JS文件 | 1-2分钟 | 强(shell循环) | 不能 |
| Python+BeautifulSoup | 精确提取script标签+下载外部JS | 1-3分钟 | 强(for循环) | 不能 |
| Puppeteer无头浏览器 | 需要动态加载的JS、SPA页面 | 3-5分钟 | 中等(资源开销大) | 能 |
一、wget递归下载,一行命令扒光整个站的所有JS文件
这是最快的方法,不需要写代码,一行命令搞定。wget是Linux自带的下载工具,Windows下可以装Git Bash或者WSL来用。
基础命令:下载单个网站的所有JS文件
wget --recursive --level=2 --accept="*.js" \--no-parent --domains=目标域名.com \--directory-prefix=./js_output \https://目标域名.com参数解释:
--recursive:递归下载,顺着页面里的链接往下爬--level=2:递归深度,设为2基本能把首页和内页的JS都抓到--accept="*.js":只下载.js文件,过滤掉HTML、CSS、图片等--no-parent:不跳出当前域名目录结构--domains:限制只在该域名下爬取,防止跟着外链跑偏--directory-prefix:保存到指定目录
进阶:批量下载多个网站的JS文件
# 把所有目标域名写到一个txt文件,一行一个# domains.txt内容:# site-a.com# site-b.com# site-c.comwhile read domain; doecho "正在采集: $domain"wget --recursive --level=2 --accept="*.js" \--no-parent --domains="$domain" \--directory-prefix="./js_collection/$domain" \"https://$domain"done < domains.txt这个脚本跑完之后,js_collection目录下每个域名一个子文件夹,里面是所有抓到的JS文件。
wget的局限:只能下载HTML源码中直接引用的外部JS文件(<script src="xxx.js">),对于JS动态加载的JS文件(比如用document.createElement('script')注入的),wget拿不到。还有就是内联JS(<script>直接写在HTML里的代码</script>)也不会被单独保存。
二、Python+BeautifulSoup,精确提取内联JS和外部JS
wget只管下载文件,不管内容分类。如果你想做更精细的操作——比如同时提取内联JS代码和外部JS文件、按JS文件名模式过滤、自动去重——Python方案更灵活。
完整脚本:提取网页中所有JS代码(内联+外部下载)
import requestsfrom bs4 import BeautifulSoupfrom urllib.parse import urljoin, urlparseimport osimport redef collect_js_from_page(url, output_dir="js_output"):"""采集单个网页的所有JS代码"""domain = urlparse(url).netlocsite_dir = os.path.join(output_dir, domain)os.makedirs(site_dir, exist_ok=True)headers = {"User-Agent": "Mozilla/5.0"}resp = requests.get(url, headers=headers, timeout=15)soup = BeautifulSoup(resp.text, "html.parser")js_files = []# 1. 提取所有外部JS文件()for i, script in enumerate(soup.find_all("script", src=False)):if script.string and script.string.strip():filename = f"inline_{i}.js"filepath = os.path.join(site_dir, filename)with open(filepath, "w", encoding="utf-8") as f:f.write(script.string)js_files.append({"type": "inline", "index": i, "file": filepath})print(f"[内联JS] 已保存: {filename} ({len(script.string)} 字符)")return js_files# 使用示例result = collect_js_from_page("https://目标域名.com")print(f"\n共提取 {len(result)} 个JS代码块")批量跑多个网站:
urls = ["https://site-a.com","https://site-b.com","https://site-c.com",]for url in urls:print(f"\n{'='*50}")print(f"正在采集: {url}")print(f"{'='*50}")collect_js_from_page(url)Python方案相比wget的优势:①能把内联JS也保存下来;②可以自定义过滤规则(比如只下载文件名包含"track"的JS);③自动按域名分目录;④失败重试机制。

三、grep+正则,从几千个JS文件里秒找到你想要的代码片段
用上面两种方法把JS文件全扒下来之后,你会面对一个现实问题:几十个站、几百个JS文件,加起来可能几十万行代码。怎么从里面找到你要的那一段?
grep是Linux/Unix下的文本搜索工具,Windows下可以用Git Bash或者安装ripgrep(rg,比grep更快)。
常用搜索场景和对应的grep命令:
| 你想找什么 | grep命令 | 说明 |
| 百度统计代码 | grep -r "hm.baidu.com" ./js_output/ | 搜百度统计的加载域名 |
| Google Analytics | grep -r "UA-\|G-" ./js_output/ | 搜GA的跟踪ID格式 |
| Google AdSense | grep -r "adsbygoogle\|googlesyndication" ./js_output/ | 搜AdSense广告代码特征 |
| 反爬逻辑 | grep -r "fingerprint\|bot\|spider\|captcha" ./js_output/ | 搜反爬关键词 |
| 前端特效(轮播/弹窗) | grep -r "swiper\|carousel\|modal\|lightbox" ./js_output/ | 搜常见UI库关键词 |
| CNZZ/友盟统计 | grep -r "cnzz.com\|umeng.com" ./js_output/ | 搜国内统计平台域名 |
显示文件名和行号,方便定位:
# -n 显示行号,-H 显示文件名,--color 高亮匹配grep -rnH --color "hm.baidu.com" ./js_output/ripgrep(rg)替代grep,速度更快
如果你有几百个JS文件要搜,ripgrep比grep快一个数量级。安装:winget install BurntSushi.ripgrep.MSVC(Windows),然后同样的命令把grep换成rg即可。ripgrep默认忽略.gitignore规则,搜代码目录不会去搜node_modules。
四、Puppeteer无头浏览器,专门对付动态加载的JS
前面三种方法都有一个共同的盲区:拿不到页面加载后通过JS动态注入的脚本。比如很多现代前端框架(React、Vue)的页面,初始HTML里只有<div id="app"></div>,真正的JS是webpack打包后动态加载的chunk文件。
这时候需要用Puppeteer(Node.js无头浏览器),它能模拟完整浏览器行为,把所有网络请求都拦截下来,包括动态加载的JS。
Puppeteer拦截并保存所有JS文件:
const puppeteer = require('puppeteer');const fs = require('fs');const path = require('path');const url = require('url');async function collectJS(targetURL, outputDir = './js_puppeteer_output') {const browser = await puppeteer.launch({ headless: "new" });const page = await browser.newPage();// 启用请求拦截await page.setRequestInterception(true);const jsFiles = [];page.on('request', (request) => {request.continue(); // 放行所有请求});page.on('response', async (response) => {const reqUrl = response.url();const contentType = response.headers()['content-type'] || '';// 只拦截JS文件if (contentType.includes('javascript') || reqUrl.endsWith('.js')) {try {const body = await response.text();const parsed = url.parse(reqUrl);const filename = path.basename(parsed.pathname) || `dynamic_${Date.now()}.js`;const filepath = path.join(outputDir, filename);if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });fs.writeFileSync(filepath, body, 'utf-8');jsFiles.push({ url: reqUrl, file: filepath, size: body.length });console.log(`[JS] 已拦截: ${filename} (${body.length} 字节)`);} catch (e) {console.log(`[JS] 读取失败: ${reqUrl}`);}}});await page.goto(targetURL, { waitUntil: 'networkidle2', timeout: 30000 });await page.waitForTimeout(3000); // 等3秒确保所有动态JS加载完await browser.close();return jsFiles;}// 使用collectJS('https://目标域名.com').then(files => {console.log(`\n共采集 ${files.length} 个JS文件`);});Puppeteer方案的代价
每个页面启动一次Chrome进程,内存占用300MB+。批量跑20个站就是20次启动和关闭浏览器,对机器的要求不低。建议在服务器上跑,本地机器可能会卡。

如果你对Node.js不熟,Python也有对应的方案——Playwright,用法几乎一样:
# 安装:pip install playwright && playwright install chromiumfrom playwright.sync_api import sync_playwrightimport osdef collect_js_playwright(url, output_dir="./js_output"):os.makedirs(output_dir, exist_ok=True)js_list = []with sync_playwright() as p:browser = p.chromium.launch(headless=True)page = browser.new_page()# 拦截所有响应page.on("response", lambda response: save_js(response, output_dir, js_list))page.goto(url, wait_until="networkidle")page.wait_for_timeout(3000)browser.close()return js_listdef save_js(response, output_dir, js_list):ct = response.headers.get("content-type", "")if "javascript" in ct or response.url.endswith(".js"):try:body = response.text()fname = response.url.split("/")[-1].split("?")[0] or f"dyn.js"path = os.path.join(output_dir, fname)with open(path, "w", encoding="utf-8") as f:f.write(body)js_list.append({"url": response.url, "size": len(body)})except:pass五、JS代码采集之后怎么用?三个实际场景
场景1:分析同行的技术栈
把JS文件全下载后grep搜"React""Vue""jQuery""webpack",能快速判断对方用什么框架和打包工具。搜"axios""fetch""XMLHttpRequest"能看到对方的前端API请求方式。
场景2:统计和广告代码排查
想知道同行用了哪些统计和变现手段,grep搜"hm.baidu.com""googletagmanager""adsbygoogle""cnzz",一秒钟出结果,比手动翻网页快100倍。
场景3:前端特效和交互实现
看到某个网站的动画效果特别好,把JS扒下来搜动画相关的函数名,研究实现逻辑。搜"animate""transition""transform""requestAnimationFrame"等关键词。
六、JS混淆代码的处理
一个让人头疼的问题是:很多网站的JS代码是压缩混淆过的。你以为下载到了源文件,打开一看是一行十几万字符的乱码。这种代码grep搜关键词可能搜不到——因为变量名都被替换成了a、b、c。
处理思路:
- 先格式化:用在线工具(如beautifier.io)或VS Code的格式化功能(Shift+Alt+F),把压缩代码展开成多行,至少能看清结构
- 搜字符串常量:混淆改的是变量名和函数名,但字符串常量(比如URL、API路径、配置项)通常不变。grep搜"https://""api.""track""log"等字符串,比搜函数名有效
- 搜域名特征:统计代码、广告代码一定会请求外部域名。搜".com""api."这类模式,定位网络请求的部分
- AST反混淆:如果确实需要深入分析,可以用Babel解析AST,写规则自动还原混淆代码。这个门槛比较高,一般情况用不到
法律提醒
JS代码属于网站的组成部分,受著作权法保护。采集代码用于个人学习、技术研究通常问题不大,但如果直接复制别人的JS代码用于商业项目,可能涉及侵权。采集之前看清楚网站的robots.txt和使用条款。
七、完整工作流:从URL列表到分类好的JS代码库
把前面的方法串起来,形成一个自动化流水线:
#!/bin/bash# 完整的JS批量采集+分类脚本URL_LIST="urls.txt" # 目标网站列表,一行一个JS_OUTPUT="./js_database" # JS文件保存目录REPORT="report.txt" # 分析报告> $REPORT # 清空报告while read domain; doecho "===== $domain =====" | tee -a $REPORT# Step 1: 用wget下载JS文件wget -q --recursive --level=2 --accept="*.js" \--no-parent --domains="$domain" \--directory-prefix="$JS_OUTPUT/$domain" \"https://$domain"# Step 2: 用grep分析每个站的JS特征DIR="$JS_OUTPUT/$domain"echo " 统计代码:" | tee -a $REPORTgrep -rl "hm.baidu.com\|googletagmanager\|cnzz.com" $DIR 2>/dev/null | tee -a $REPORTecho " 广告代码:" | tee -a $REPORTgrep -rl "adsbygoogle\|googlesyndication\|adnxs" $DIR 2>/dev/null | tee -a $REPORTecho " 前端框架:" | tee -a $REPORTgrep -rl "React\|Vue\|Angular\|jQuery" $DIR 2>/dev/null | tee -a $REPORTecho " JS文件总数:" | tee -a $REPORTfind $DIR -name "*.js" | wc -l | tee -a $REPORTecho "" | tee -a $REPORTdone < $URL_LISTecho "全部完成!报告保存在 $REPORT"这个脚本跑完,每个网站的JS文件按域名分好文件夹,同时生成一份报告,告诉你每个站用了什么统计代码、什么广告代码、什么前端框架。
最后说两句
JS代码采集这件事,关键不是工具多高级,而是你要想清楚"到底要找什么"。目标明确的话,wget+grep两个命令就够用了,一个负责下载,一个负责搜索,5分钟出结果。只有遇到动态加载的SPA页面,才需要上Puppeteer或Playwright。别一上来就上重武器,大多数场景根本用不到。另外提一句,如果你用UC建站这类平台搭建的网站,前端JS文件通常由平台统一管理和压缩优化,想分析模板自带的功能逻辑直接在后台模板编辑器里看源码就行,不需要单独采集。
