如何抓取由JS动态生成的FCC许可证页面表格数据?
如何抓取由JS动态生成的FCC许可证页面表格数据?
遇到这种用JS动态生成的表格,核心问题是:你用requests拿到的只是页面的初始HTML和JS代码,而表格内容是浏览器加载页面后,执行JS才从后端拉取数据并渲染出来的,静态请求自然抓不到最终的表格HTML。
这里有两个实用的解决思路,你可以根据自己的情况选择:
方法1:模拟真实浏览器渲染页面(新手友好)
这种方法会启动一个真实的浏览器(比如Chrome、Firefox),等待页面的JS执行完成、表格渲染好之后,再抓取页面内容。常用的工具是Selenium或者Playwright,后者现在更轻量、易用。
举个Playwright的代码示例:
from playwright.sync_api import sync_playwright url = "https://wireless2.fcc.gov/UlsApp/UlsSearch/leasesList.jsp?licKey=2591153" with sync_playwright() as p: # 启动后台运行的浏览器(headless=True表示不弹出窗口) browser = p.chromium.launch(headless=True) page = browser.new_page() # 打开目标页面,等待网络请求全部完成(确保表格渲染完毕) page.goto(url, wait_until="networkidle") # 抓取渲染后的完整表格HTML table_html = page.locator("table").inner_html() # 也可以直接提取表格每一行的文本内容 row_texts = page.locator("table tr").all_inner_texts() # 保存结果到文件 with open("rendered_leases_table.html", "w", encoding="utf-8") as f: f.write(table_html) browser.close()
用这种方法,你就能拿到和浏览器里看到的完全一致的渲染后内容,包括完整的表格数据。
方法2:直接抓取JS调用的后端接口(更高效推荐)
JS能生成表格,肯定是从后端的某个接口拉取了原始结构化数据(一般是JSON格式),直接调用这个接口拿数据,比模拟浏览器要快得多,也更省资源。你可以按照以下步骤找到这个接口:
- 打开浏览器开发者工具(按F12),切换到「网络」标签页
- 刷新目标页面,然后在网络请求列表里,点击「筛选」按钮,选择「XHR」或者「Fetch」类型(这些就是JS发起的异步数据请求)
- 逐个查看这些请求的响应内容,找到返回表格数据的那个请求(通常响应是JSON格式,里面会包含表格的所有行数据)
- 复制这个请求的URL、请求参数和必要的请求头(比如
User-Agent要模拟浏览器,避免被拦截),然后用requests直接发送请求
比如,假设你找到的数据源接口URL是https://wireless2.fcc.gov/UlsApp/LeasesDataServlet,参数包含licKey=2591153,代码大概是这样:
import requests # 模拟浏览器的请求头,避免被接口拦截 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", "Referer": "https://wireless2.fcc.gov/UlsApp/UlsSearch/leasesList.jsp?licKey=2591153" } url = "https://wireless2.fcc.gov/UlsApp/LeasesDataServlet" params = { "licKey": "2591153", # 其他可能的参数可以从浏览器请求里复制 } response = requests.get(url, headers=headers, params=params) table_data = response.json() # 现在table_data就是结构化的表格数据,直接处理即可 for row in table_data: print(row)
这种方法的关键是找到真实的数据源接口,FCC的这类政务系统一般会用XHR请求拉取表格数据,仔细筛选网络请求肯定能定位到。如果遇到接口需要特定的请求头(比如Referer),直接从浏览器的请求详情里复制过来就行,确保请求和浏览器发送的完全一致。
你之前尝试找底层查询结构的思路非常对,只是没找到对应的接口,用上面的网络面板筛选方法,应该能快速定位到目标接口。
备注:内容来源于stack exchange,提问作者Jonsey
相关产品推荐
相关产品推荐

