使用R抓取含表单及JS的网站:POST提交后仍获旧数据求助
解决动态JS生成内容的爬虫问题
嘿,这个问题我之前也碰到过不少——很多依赖JS渲染的网站,表面上是表单提交,但实际背后是通过AJAX调用后台API来获取数据,直接模拟表单POST肯定拿不到结果。针对你这个距离计算器网站,我给你两个可行的解决方案:
方法一:直接调用后台API(高效首选)
这个网站的Calculate按钮点击后,并没有把表单数据直接提交到服务器返回新页面,而是用JavaScript偷偷发了一个API请求去拿计算好的距离数据,再渲染到页面上。所以我们可以跳过前端页面,直接跟这个API打交道:
抓包找到真实API
- 打开浏览器的开发者工具(按F12),切换到「Network」标签页。
- 正常输入你要查询的两个城市,点击「Calculate」按钮,观察Network里的请求列表。你会看到一个新的请求(可能是POST或GET方法),它的响应内容就是距离相关的JSON数据。
- 记下这个API的URL、请求方法(POST/GET)、需要的参数(比如
from、to、units这些,可能是地点字符串或者经纬度),还有请求头里的必要信息(比如User-Agent,有些网站会校验这个)。
用爬虫直接请求API
比如用Python的requests库,直接构造请求发送给这个API,就能拿到结构化的结果,不用处理复杂的页面渲染。举个简化的例子(具体参数要根据你抓包的结果调整):import requests url = "https://www.distancecalculator.net/api/your-found-api-endpoint" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } data = { "from": "Craíbas - AL, Brasil", "to": "Maceió - AL, Brasil", "units": "km" # 假设单位参数是km } response = requests.post(url, headers=headers, data=data) result = response.json() print(f"距离:{result['distance']} {result['unit']}")
方法二:用无头浏览器模拟用户操作(稳定可靠)
如果抓API觉得麻烦,或者网站的API有反爬机制,那可以用无头浏览器(比如Selenium、Playwright)完全模拟真实用户的操作,让浏览器帮你执行JS并渲染出结果:
以Selenium为例,代码大概是这样的:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 启动无头Chrome(不会弹出浏览器窗口) options = webdriver.ChromeOptions() options.add_argument('--headless=new') driver = webdriver.Chrome(options=options) try: # 打开目标网站 driver.get("https://www.distancecalculator.net/") # 填写出发地和目的地 from_input = driver.find_element(By.ID, "from") from_input.send_keys("Craíbas - AL, Brasil") to_input = driver.find_element(By.ID, "to") to_input.send_keys("Maceió - AL, Brasil") # 点击Calculate按钮 calculate_btn = driver.find_element(By.XPATH, '//button[contains(text(), "Calculate")]') calculate_btn.click() # 等待结果加载完成(最多等10秒) distance_result = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CLASS_NAME, "distance-number")) # 这个类名要根据页面实际元素调整 ) print(f"计算结果:{distance_result.text}") finally: # 关闭浏览器 driver.quit()
注意事项
- 方法一效率更高,适合批量爬取,但要注意API可能会随时变化(比如参数、URL),需要定期检查抓包结果。
- 方法二更稳定,不容易触发反爬,但速度慢、消耗资源多,适合少量查询。
- 不管用哪种方法,都要遵守网站的使用条款,不要频繁请求,避免被封禁IP。
内容的提问来源于stack exchange,提问作者Diego Rodrigues
相关产品推荐
相关产品推荐

