You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python爬取Deliveroo多站点商品名称与价格问题求解

Deliveroo站点商品爬取方案

单站点商品名、价格提取

你之前卡在数据提取环节的核心问题是写死了完整的class属性值——Deliveroo前端类名末尾带随机生成的哈希串,会随版本迭代变动,硬写全值很容易匹配失败,同时不需要手动逐层追溯嵌套节点,直接按特征匹配目标标签即可。
提取逻辑:

  • 商品卡片统一以UIMenuItemCard为类名前缀,用前缀匹配定位所有商品容器
  • 商品名存放在卡片内类名前缀为ccl-的p标签中
  • 价格存放在卡片内带欧元符号€的span标签中,通过文本特征匹配避免抓错无关标签
    可直接运行的单站点提取代码:
import requests
from bs4 import BeautifulSoup
import pandas as pd

url = "https://deliveroo.it/en/menu/jesolo/jesolo/burger-king-jesolo"
# 加请求头模拟正常浏览器访问,避免被反爬拦截
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
resp = requests.get(url, headers=headers)
soup = BeautifulSoup(resp.text, "html.parser")

product_list = []
for card in soup.find_all("div", class_=lambda x: x and x.startswith("UIMenuItemCard")):
    name_tag = card.find("p", class_=lambda x: x and x.startswith("ccl-"))
    price_tag = card.find("span", string=lambda t: t and "€" in t)
    if name_tag and price_tag:
        product_list.append({
            "name": name_tag.get_text(strip=True),
            "price": price_tag.get_text(strip=True).replace("€", "").strip()
        })

df_single = pd.DataFrame(product_list)
print(df_single)

运行后输出的结构化数据和你给出的示例格式完全一致。

多站点批量爬取+结果合并+站点间空行分隔

你原有批量代码仅返回最后一个站点数据的核心原因:db_name、db_price列表的初始化放在了for循环内部,每次遍历新URL时都会清空之前存储的爬取结果,循环结束后自然只保留最后一个站点的数据。另外你原代码中的URL被手动拆成了多行,会导致请求地址无效。
实现逻辑:

  • 将存储全量数据的列表移到循环外部初始化,避免每次遍历重置数据
  • 每爬完一个非末尾站点的所有商品,往结果集中插入一条空记录,实现站点间空行分隔
  • 爬取完成后一次性转换为DataFrame,无需拆分name、price分别建表再合并
    修正后的可运行代码:
import time
import requests
from bs4 import BeautifulSoup
import pandas as pd

siti = [
    "https://deliveroo.it/it/menu/roma/piazza-venezia/burger-king-via-nazionale",
    "https://deliveroo.it/en/menu/jesolo/jesolo/burger-king-jesolo",
    "https://deliveroo.it/it/menu/roma/via-tiburtina/burger-king-via-tiburtina"
]

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

all_products = []

for idx, url in enumerate(siti):
    resp = requests.get(url, headers=headers)
    soup = BeautifulSoup(resp.text, "html.parser")
    # 提取当前站点所有商品
    for card in soup.find_all("div", class_=lambda x: x and x.startswith("UIMenuItemCard")):
        name_tag = card.find("p", class_=lambda x: x and x.startswith("ccl-"))
        price_tag = card.find("span", string=lambda t: t and "€" in t)
        if name_tag and price_tag:
            all_products.append({
                "name": name_tag.get_text(strip=True),
                "price": price_tag.get_text(strip=True).replace("€", "").strip()
            })
    # 非最后一个站点,爬完后插入空行做分隔
    if idx != len(siti) - 1:
        all_products.append({"name": "", "price": ""})
    # 加2秒延迟,避免请求过频被反爬拦截
    time.sleep(2)

df_all = pd.DataFrame(all_products)
# 导出为csv文件,用utf-8-sig编码避免乱码
df_all.to_csv("deliveroo_all_products.csv", index=False, encoding="utf-8-sig")
print(df_all)

注意事项

  • 不要硬编码完整的class属性值,Deliveroo前端发版会更新类名后的哈希后缀,前缀匹配的方式稳定性更高
  • 如果出现部分商品匹配不到的情况,可以先打印soup.prettify()确认返回的页面源码中是否包含目标商品,大概率是被反爬拦截,调整请求头、增加请求延迟即可解决

内容的提问来源于stack exchange,提问作者Davide

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 00:51:24