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

Python3.7+BeautifulSoup爬取TripAdvisor仅获首条评论问题排查

问题分析与修复方案

我帮你排查了代码里的几个关键问题,这些就是导致你只能获取第一条评论信息的核心原因:

1. URL分页参数完全错误

你当前的URL里用了.format(i)但没有任何占位符(比如{}),而且TripAdvisor的分页逻辑是orX,其中X是跳过的评论数量,第N页对应的X值是(N-1)*10(因为每页显示10条评论)。你现在的URL固定是or10,所以循环i从10到40时,每次请求的都是同一页(第2页),这直接导致后续页面的评论根本没被爬取。

2. 评论容器的选择与遍历逻辑混乱

你用gen_rest = page_soup.find_all("div", {"class":"page"})拿到的是整个页面的根容器,然后嵌套for clients in gen_rest,相当于在整个页面容器里重复遍历,而不是定位到单个评论卡片。正确的做法是找到页面中所有独立的评论项,比如TripAdvisor里评论的容器通常是div.review-container。

3. 始终只取第一个评论的元素

你在获取客户姓名、评论日期等信息时,都用了[0].text,比如client_info[0].text,这会强制只取每个选择器匹配到的第一个元素,自然只能拿到第一条评论的内容。


修正后的代码

下面是修复后的完整代码,我加入了注释说明关键修改点:

import csv
import requests
from bs4 import BeautifulSoup

# 用with语句自动管理文件,避免手动关闭的问题
with open("lebouclard.csv", "w", encoding="utf-8", newline="") as csv_file:
    csv_writer = csv.writer(csv_file, delimiter=";")
    csv_writer.writerow(["inf_rest_name", "rest_eclf", "name_client", "date_rev_cl", "titre_rev_cl", "opinion_cl"])
    
    # 遍历第10到40页(注意range是左闭右开,所以到41)
    for page_num in range(10, 41):
        # 计算分页参数:第page_num页对应跳过(page_num-1)*10条评论
        skip_num = (page_num - 1) * 10
        # 正确格式化URL,替换or后面的数字
        url = f"https://www.tripadvisor.fr/Restaurant_Review-g187147-d947475-Reviews-or{skip_num}-Le_Bouclard-Paris_Ile_de_France.html"
        response = requests.get(url)
        # 检查请求是否成功,避免无效页面
        if response.status_code != 200:
            print(f"页面{page_num}请求失败,状态码:{response.status_code}")
            continue
        page_soup = BeautifulSoup(response.text, "html.parser")
        
        # 获取餐厅名称和社会经济地位(整个页面只需要取一次)
        rname = page_soup.find("h1", {"class": "ui_header h1"})
        inf_rest_name = rname.text.strip() if rname else "未知名称"
        
        econ_class_food = page_soup.find("div", {"class": "header_links"})
        rest_eclf = econ_class_food.text.strip() if econ_class_food else "未知分类"
        
        # 定位所有评论卡片
        reviews = page_soup.find_all("div", {"class": "review-container"})
        if not reviews:
            print(f"页面{page_num}未找到评论")
            continue
        
        # 遍历每条评论
        for review in reviews:
            # 获取客户姓名
            client_info = review.find("div", {"class": "info_text"})
            name_client = client_info.text.strip() if client_info else "匿名用户"
            
            # 获取评论日期
            date_review = review.find("span", {"class": "ratingDate"})
            # 注意:TripAdvisor的日期可能在title属性里,比如"评论日期:2024年5月1日"
            date_rev_cl = date_review.get("title", date_review.text.strip()) if date_review else "未知日期"
            
            # 获取评论标题
            titre_review = review.find("span", {"class": "noQuotes"})
            titre_rev_cl = titre_review.text.strip() if titre_review else "无标题"
            
            # 获取评论内容
            opinion = review.find("p", {"class": "partial_entry"})
            opinion_cl = opinion.text.replace("\n", "").strip() if opinion else "无内容"
            
            # 写入CSV
            csv_writer.writerow([inf_rest_name, rest_eclf, name_client, date_rev_cl, titre_rev_cl, opinion_cl])
            print(f"已写入页面{page_num}的评论:{name_client}")

额外说明

  • 加入了请求状态码检查,避免爬取无效页面;
  • 增加了空值判断,防止某个元素找不到导致代码报错;
  • 用f-string格式化URL更直观;
  • 使用with语句管理文件,无需手动调用close();
  • 注意TripAdvisor的评论日期可能存储在title属性中,而不是直接的文本,所以代码里做了兼容处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:07:50