Python爬取问题:链接内容变化及requests无法获取特定表格
嘿,我来帮你解决这两个爬虫问题,都是实际爬取中常见的场景,咱们一个个来:
这其实是批量爬取里的典型场景,核心就是遍历链接池 + 按需解析每个页面,给你拆解成可落地的步骤:
第一步:整理目标链接列表
你可以手动把所有需要爬的链接存到一个列表里,或者先爬取一个汇总页面(比如政治人物的列表页),用BeautifulSoup提取所有目标链接的href属性,生成链接池。比如:import requests from bs4 import BeautifulSoup # 假设这是汇总页面URL list_url = "https://example.com/politicians" headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"} response = requests.get(list_url, headers=headers) soup = BeautifulSoup(response.text, "html.parser") # 提取所有政治人物的详情页链接 link_pool = [a["href"] for a in soup.select("div.politician-item a")]第二步:批量遍历并请求页面
遍历链接池里的每个链接,逐个发起请求。这里一定要注意反爬措施:加请求头模拟浏览器、设置请求间隔(避免给服务器太大压力)、处理请求异常(比如超时、404)。示例:import time for link in link_pool: try: # 处理相对链接,拼接成完整URL full_link = "https://example.com" + link if not link.startswith("http") else link response = requests.get(full_link, headers=headers, timeout=10) response.raise_for_status() # 抛出HTTP错误 # 这里调用解析函数处理当前页面 parse_page(response.text) time.sleep(1) # 间隔1秒,可根据情况调整 except Exception as e: print(f"爬取{full_link}失败: {str(e)}") continue第三步:按需解析每个页面
因为每个页面内容不同,你可以根据页面的特征(比如URL包含的关键词、页面里的特定标识)来分支处理解析逻辑。如果是同一类站点的不同详情页,大概率核心内容的标签/class是有规律的,比如提取标题、描述、表格等:def parse_page(html): soup = BeautifulSoup(html, "html.parser") # 提取页面标题 title = soup.find("h1").get_text(strip=True) # 提取特定内容,比如不同页面可能有不同的模块,可根据实际情况调整 description = soup.find("div", class_="desc").get_text(strip=True) if soup.find("div", class_="desc") else "无描述" # 存储数据,比如写入CSV with open("politicians_data.csv", "a", encoding="utf-8") as f: f.write(f"{title},{description}\n")第四步:数据存储
把每个页面爬取到的数据统一存储,推荐用CSV、JSON或者SQLite,方便后续分析和查看。
这种情况99%是因为表格内容是JavaScript动态渲染的(比如通过AJAX异步加载、或者前端框架渲染),requests只能拿到静态HTML,自然找不到表格元素。给你两种解决方案,按优先级推荐:
方案1:直接请求数据接口(高效首选)
很多网站的动态表格数据是通过XHR/Fetch请求从后端接口获取的,你可以通过浏览器开发者工具找到这个接口:
- 打开目标页面,按F12打开开发者工具,切换到「Network」标签;
- 刷新页面,在「XHR」或「Fetch」分类下找返回JSON数据的请求,查看请求URL、参数和响应内容;
- 如果找到对应表格的接口,直接用
requests请求这个接口,拿到JSON数据后解析成表格即可。
示例代码:
import requests import json # 假设找到的接口URL,可能需要携带特定参数(比如政治人物ID) api_url = "https://example.com/api/politician/assets" params = {"politician_id": "123"} # 每个政治人物的ID不同,需要从详情页提取或者遍历 headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"} response = requests.get(api_url, params=params, headers=headers) data = response.json() # 解析JSON数据,提取"Descrição""Tipo""Valor do Bem"字段 for item in data["assets"]: descricao = item.get("descricao") tipo = item.get("tipo") valor = item.get("valor_do_bem") print(f"Descrição: {descricao}, Tipo: {tipo}, Valor: {valor}")
方案2:用无头浏览器渲染页面(适合复杂场景)
如果找不到接口或者接口有加密/反爬,那就用无头浏览器模拟真实浏览器加载页面,等待JS渲染完成后再提取表格。推荐用Playwright(比Selenium更简洁,自带浏览器驱动):
先安装Playwright:
pip install playwright playwright install chrome示例代码(针对每个政治人物页面处理):
from playwright.sync_api import sync_playwright import time def crawl_dynamic_table(url): with sync_playwright() as p: browser = p.chromium.launch(headless=True) # headless=True表示无界面模式 page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") page.goto(url, wait_until="networkidle") # 等待网络空闲,确保内容加载完成 # 定位表格,假设表格有特定的class或ID table = page.locator("table.assets-table") # 遍历表格行,跳过表头 rows = table.locator("tr").all()[1:] for row in rows: descricao = row.locator("td:nth-child(1)").text_content().strip() tipo = row.locator("td:nth-child(2)").text_content().strip() valor = row.locator("td:nth-child(3)").text_content().strip() print(f"Descrição: {descricao}, Tipo: {tipo}, Valor: {valor}") browser.close() # 遍历每个政治人物的URL politician_urls = ["https://example.com/politician/1", "https://example.com/politician/2"] for url in politician_urls: crawl_dynamic_table(url) time.sleep(1)
注意:如果用Selenium的话,步骤类似,但需要手动下载对应浏览器的驱动,代码会稍微繁琐一点。
内容的提问来源于stack exchange,提问作者Reinaldo Chaves




