使用BeautifulSoup无法提取网页部分图片跳转链接的问题咨询
问题根因
你提取不到画作详情链接的核心原因非常明确:
requests只能拿到页面首次返回的静态HTML源码,而这个页面的画作列表完全是JavaScript异步加载渲染的:页面初始返回的内容只有导航栏、广告、页脚这些固定模块,画作数据是浏览器加载完基础页面后,单独发异步请求拉取,再通过JS插入到页面DOM里的。requests没有浏览器的JS执行能力,自然拿不到这部分动态生成的内容。- 你观察到按住Ctrl点击图片无法新开标签页的现象刚好能佐证这点:初始静态DOM里的图片卡片根本不是带
href属性的标准<a>标签,只是绑定了点击跳转事件的普通块级元素,等JS拉取完数据完成渲染后才会补全跳转逻辑,你在静态源码里用正则匹配https://开头的a标签,当然找不到目标链接。
解决方案
你可以根据自己的需求二选一:
方案1:直接调用站点的数据接口(推荐,速度快、资源占用低)
这类动态加载的页面,本质都是浏览器向服务端接口请求结构化数据,你不需要模拟浏览器运行,直接请求对应接口就能拿到完整的画作信息,里面自带详情页地址。
操作方法很简单:打开目标页面后按F12调出浏览器开发者工具,切换到「网络」面板,筛选Fetch/XHR类型的请求,滚动页面触发画作加载,就能找到返回画作列表数据的接口。接口返回的是JSON格式的结构化数据,每个画作条目包含作者标识、画作详情页路径等字段,直接拼接就能得到详情页链接。
参考实现代码:
import requests api_endpoint = "https://www.wikiart.org/en/paintings-by-style/magic-realism" request_params = { "select": "featured", "json": 2, "layout": "new", "page": 1, "resultType": "masonry" } request_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" } response = requests.get(api_endpoint, params=request_params, headers=request_headers) painting_list = response.json().get("Paintings", []) for painting in painting_list: # 拼接完整详情页链接 detail_link = f"https://www.wikiart.org/en/{painting['artistUrl']}/{painting['url']}" print(detail_link)
提示:接口是分页的,你可以循环修改page参数值直到拉取完所有数据,请求时保持合理的间隔,避免触发反爬。
方案2:使用支持JS渲染的爬虫工具(适配性强,无需逆向接口)
如果不想逐个分析页面接口,你可以用能模拟真实浏览器执行JS的工具,等页面所有动态内容渲染完成后再解析DOM,就能和在浏览器里看到的内容一致。
以playwright为例,使用前先执行命令安装依赖:pip install playwright && playwright install chromium
参考实现代码:
from playwright.sync_api import sync_playwright from bs4 import BeautifulSoup target_url = "https://www.wikiart.org/en/paintings-by-style/magic-realism?select=featured#!#filterName:featured,viewType:masonry" with sync_playwright() as p: # 启动无头浏览器 browser = p.chromium.launch(headless=True) page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36") page.goto(target_url) # 等待画作卡片加载完成 page.wait_for_selector(".painting-card", timeout=10000) # 获取渲染完成后的完整页面HTML full_html = page.content() browser.close() soup = BeautifulSoup(full_html, 'html.parser') # 过滤掉导航、广告、社交媒体链接,提取画作详情链接 for link in soup.find_all("a"): href = link.get("href", "") if href.startswith("/en/") and "-" in href and not any(block_word in href for block_word in ["facebook", "twitter", "1st-art", "globalcitizen", "uservoice", "apple", "google"]): print("https://www.wikiart.org" + href)
注意:爬取公开数据时请遵守站点的robots协议,控制请求频率,不要对站点正常运行造成影响。
内容的提问来源于stack exchange,提问作者Ananda
相关产品推荐
相关产品推荐

