请求协助:爬取Subway Menara UOA Bangsar门店名称失败问题排查
请求协助:爬取Subway Menara UOA Bangsar门店名称失败问题排查
嘿,咱们来看看你的爬取代码为啥没返回数据!我仔细看了你的代码和Subway马来西亚的官网,找到了几个关键问题和对应的修复方法:
问题根源分析
- 动态内容加载:你要定位的
fp_locationlistdiv其实是页面加载后通过JavaScript动态填充数据的。当你用requests.get()请求时,只能拿到静态的HTML骨架——那些门店数据根本没包含在里面。这就导致loc变量变成了None,自然拿不到任何结果。 - 代码逻辑小问题:就算静态HTML里有数据,你用
loc.find('div', class_='fp_ll_holder')只能获取单个元素,而不是列表。直接遍历单个div是不会得到预期结果的,应该用find_all()来获取所有门店容器。
解决方案
方案1:用Selenium渲染动态内容(新手友好)
Selenium可以控制真实浏览器,帮你执行JavaScript并加载完整的页面内容。调整后的代码如下:
首先安装Selenium和Chrome驱动(或者你常用的浏览器驱动):
pip install selenium
然后是代码:
from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.options import Options import time # 设置无头模式,避免弹出浏览器窗口 chrome_options = Options() chrome_options.add_argument('--headless=new') driver = webdriver.Chrome(options=chrome_options) url = 'https://subway.com.my/find-a-subway' driver.get(url) # 等待几秒,让JavaScript加载完数据 time.sleep(3) # 获取完全渲染后的HTML page_source = driver.page_source soup = BeautifulSoup(page_source, 'html.parser') loc = soup.find('div', id='fp_locationlist') if loc: # 用find_all获取所有门店容器 outlets = loc.find_all('div', class_='fp_ll_holder') for outlet in outlets: name = outlet.find('h4').text.strip() print(name) else: print("找不到门店列表的div元素") driver.quit()
方案2:直接调用API(更高效)
打开浏览器开发者工具(F12 → 网络 → XHR),你会发现网站是通过一个API接口获取门店数据的。直接调用这个API比解析HTML高效得多:
import requests # 门店数据的API接口 api_url = 'https://subway.com.my/wp-admin/admin-ajax.php' payload = { 'action': 'store_search', 'lat': '', 'lng': '', 'max_results': '100', 'search_radius': '50', 'autoload': 'true' } response = requests.post(api_url, data=payload) data = response.json() for store in data: print(store['store']) # 还能获取地址、电话等其他信息: # print(store['address']) # print(store['phone'])
这种方式直接拿到结构化的JSON数据,不需要解析HTML,速度更快也更可靠。
额外提示
- 在访问元素属性(比如
outlet.find('h4').text)之前,一定要先检查元素是否存在,避免触发AttributeError。 - 对于动态加载的网站,用浏览器开发者工具查看网络请求能省很多时间——找找那些加载你需要的数据的XHR/fetch请求。
备注:内容来源于stack exchange,提问作者Thaariq Irfan
相关产品推荐
相关产品推荐

