先举个生活例子:你去奶茶店买奶茶,告诉店员要一杯珍珠奶茶(这就像用Python发请求),如果店员直接把奶茶递给你(数据直接在页面里),你不用多费劲;但如果店员说“珍珠要现煮,等5分钟再给你”(数据需要动态加载),你只站在原地等,永远拿不到珍珠——这就是纯Python爬虫的困境,而JS,就是帮你拿到“珍珠”的关键。
很多人学爬虫,以为把Python学明白就够了,毕竟爬虫常用的requests、BeautifulSoup、Scrapy,全是Python的工具。但实际操作起来才发现:打开网页能看到的数据,用Python爬出来全是空的,要么就是一堆乱码,这到底是为什么?
一、网页分两种,Python只“认识”第一种
我们平时看的网页,其实分静态和动态两种,就像两种不同的奶茶店,Python的“能力”只够应对第一种。
1. 静态网页(老式奶茶店)
数据直接写在网页的HTML代码里,就像奶茶和珍珠提前做好,你点单就能直接拿。用Python的requests库,就能轻松拿到所有数据,代码特别简单:
import requestsfrom bs4 import BeautifulSoup# 请求静态网页(模拟可用链接,仅用于代码演示)response = requests.get("https://mock-static-page.com")# 解析HTML,直接拿到数据soup = BeautifulSoup(response.text, "html.parser")data = soup.find("div", class_="data").textprint(data) # 直接输出网页上的可见数据
这种网页现在越来越少,大多是一些老旧的官网、静态博客,占比不足10%。
2. 动态网页(新式奶茶店)
网页打开时,只加载一个“空壳”HTML,数据需要通过JavaScript(简称JS)动态请求、加载,就像珍珠要现煮、配料要现加。这时候你用上面的Python代码爬,拿到的只有“空壳”,根本没有数据。
比如我们常用的某短视频平台、某电商商品列表,你往下滑动,数据会不断刷新,这些刷新的数据,全是JS悄悄加载进来的——纯Python,看不到这些“悄悄加载”的过程。
二、爬虫学JS,3个核心用途(附代码/场景)
不用把JS学得多深,不用像前端工程师那样写页面、做交互,只要掌握3个核心用途,就能搞定95%的主流网站爬虫。
1. 找真实接口(最常用,没有之一)
动态网页的数据,都藏在“接口”里,而这些接口,是JS发起的请求。不懂JS,你根本找不到接口地址,就像找不到奶茶店的后厨,永远拿不到珍珠。
举个例子:打开某电商商品页,用浏览器按F12(开发者工具),找到“Network”→“XHR”,就能看到JS发起的接口请求,接口返回的就是纯数据(JSON格式)。
我们可以用Python模拟这个JS请求,直接拿到数据,代码如下(以模拟JS接口请求为例):
import requestsimport execjs # 用于执行JS代码(爬虫逆向常用)# 重点:这个接口虽能用Python请求,但接口地址、参数规则全靠JS逆向获取(模拟可用接口)url = "https://mock-api.com/api/goods/list"# 1. 先通过JS逆向(核心步骤,纯Python做不到)# 假设网站通过JS生成请求头里的token(反爬常用手段),JS代码如下(实际需从网页源码中提取)js_code = '''function getToken() { // 网站真实的token生成逻辑(简化版,实际需逆向分析) let time = new Date().getTime(); return "token_" + time;}'''# 用Python调用JS代码,获取加密后的token(这就是JS逆向的核心用途)ctx = execjs.compile(js_code)token = ctx.call("getToken")# 2. 构造请求参数(参数规则也需通过JS逆向得知,比如size的取值范围、category的加密规则)params = {"page": 1,"size": 10,"category": "phone","token": token # 这个关键参数,纯Python无法生成,必须靠JS逆向}# 3. 模拟JS发起请求(请求头、参数都依赖JS逆向结果)headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36","token": token}response = requests.get(url, params=params, headers=headers)data = response.json() # 成功获取数据(核心依赖JS逆向拿到的token)print(data["goods_list"]) # 输出商品列表
这里重点说明:你说的JS逆向,正是爬虫学JS的核心!这段代码看似是Python写的,但关键的token参数、接口规则,全靠JS逆向才能获取——纯Python只能“照猫画虎”发起请求,却无法搞定这些由JS控制的反爬逻辑。
比如这个token,是网站通过JS动态生成的(真实网站的逻辑会更复杂,可能涉及sign加密、cookie验证等),纯Python根本不知道它的生成规则,请求会直接被拦截;只有通过JS逆向,分析网页里的JS代码,才能还原token的生成逻辑,进而用Python调用JS代码获取有效参数,这才是JS在爬虫中的核心价值,也是纯Python搞不定的地方。
2. 破解加密参数(反爬的“拦路虎”)
很多网站为了防止被爬,会对请求参数进行加密,比如添加sign、token等加密字段,而这些加密逻辑,全写在JS里。不懂JS,你根本不知道这些参数是怎么来的,请求会直接被拦截。
比如某网站的请求参数里,有一个sign字段,JS里的加密逻辑大概是这样(简化版):
// JS加密函数(简化版)functiongetSign(params) {// 把参数拼接成字符串let str = Object.keys(params).sort().map(key => key + params[key]).join("");// 简单加密(实际可能更复杂)return str + "abc123";}
我们只要看懂这段JS代码,用Python还原加密逻辑,就能生成正确的sign参数,避免被反爬,Python还原代码如下:
defget_sign(params):# 还原JS的加密逻辑 str_list = sorted(params.keys()) str_join = "".join([key + str(params[key]) for key in str_list])return str_join + "abc123"# 构造参数params = {"id": 123, "time": 1680000000}# 生成加密参数params["sign"] = get_sign(params)# 发起请求,顺利拿到数据(模拟可用接口)response = requests.get("https://mock-api.com/api/data", params=params)
3. 处理动态渲染页面
像Vue、React框架开发的网站,页面完全由JS渲染,纯Python请求只能拿到空HTML。这时候我们需要用Selenium/Playwright,模拟浏览器执行JS,才能拿到渲染后的完整数据。
用Playwright执行JS的简单代码(模拟加载动态页面):
from playwright.sync_api import sync_playwrightwith sync_playwright() as p:# 启动浏览器,模拟真人操作 browser = p.chromium.launch(headless=False) page = browser.new_page()# 打开动态网页(模拟可用链接,仅用于代码演示) page.goto("https://mock-dynamic-page.com")# 执行JS,获取动态加载的数据(模拟浏览器渲染) data = page.evaluate("document.querySelector('.dynamic-data').innerText") print(data) # 拿到动态加载的数据 browser.close()
总结
Python是爬虫的“工具”,能帮你写脚本、发请求;而JS是爬虫的“眼睛”,能帮你找到数据藏在哪、破解反爬、拿到动态数据。
不学JS,只能爬静态网站;学会JS,主流网站的爬虫才能畅通无阻——Python+JS,才是完整的爬虫能力。