Python3.9抓取带Load More按钮的迪拜世博会展馆数据及CSV写入问题
问题解决方案
已知问题根因
- 动态加载问题:
Load More按钮触发的是JS异步请求拉取后续页数据,requests默认只能拉取页面初始加载的第一页静态内容,无法捕获后续异步加载的数据 - CSV无内容问题:
- 代码中在提取函数里先以覆盖写模式打开了一次CSV文件,没有写入任何内容就关闭,已经清空了文件内容
- 原代码使用的元素class选择器匹配规则错误,无法抓取到对应展馆条目,导致存储数据的列表始终为空
最优实现方案
不用模拟浏览器点击,直接抓后端异步加载的接口请求即可,效率更高,完整可运行代码如下:
import requests from bs4 import BeautifulSoup import csv # 初始页面URL和异步加载接口URL base_url = "https://www.expo2020dubai.com/en/understanding-expo/participants/country-pavilions" api_url = "https://www.expo2020dubai.com/api/FilterListing/RenderFilteredItems" 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", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Referer": base_url } result = [] page = 1 while True: # 异步接口请求参数 payload = { "listingId": "63861", "page": page, "filters%5B0%5D%5BfilterKey%5D": "ContentType", "filters%5B0%5D%5BfilterValues%5D%5B0%5D": "CountryPavilion" } resp = requests.post(api_url, headers=headers, data=payload) # 接口返回空时说明没有更多数据,结束循环 if resp.text.strip() == "": break soup = BeautifulSoup(resp.text, "html.parser") items = soup.find_all(class_="c-innovator-card") if not items: break for item in items: country_elem = item.find(class_="content__title") district_elem = item.find(class_="content__subtitle") if country_elem and district_elem: country = country_elem.get_text(strip=True).replace(" Pavilion", "") district = district_elem.get_text(strip=True) result.append([country, district]) page += 1 # 写入CSV with open("pavillons.csv", "w", encoding="utf-8-sig", newline="") as f: writer = csv.writer(f) writer.writerow(["国家名称", "所属展区"]) writer.writerows(result) print(f"共抓取到{len(result)}条展馆数据,已写入CSV文件")
代码说明
- 直接调用后端分页接口,循环拉取所有页数据,直到接口返回空内容停止
- 修正了元素选择规则,准确匹配每个展馆卡片的国家和展区字段
- 使用utf-8-sig编码写入CSV,避免在Excel中打开出现中文乱码
- 额外添加了表头,方便直接查看CSV内容
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

