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
相关产品推荐
相关产品推荐

