使用BeautifulSoup爬取商品数据出现重复问题求助
商品数据重复问题排查与解决
问题根源分析
代码里存在以下核心问题导致数据重复及异常:
- productlink列表未重置:若后续爬取多页,每次循环会持续追加新链接,旧链接不会被清空,引发重复爬取同一商品
- 品牌数据处理逻辑错误:品牌信息获取放在商品详情页爬取之后,且每添加一个品牌就写入CSV,造成重复写入
- CSV写入时机错误:写入操作嵌套在品牌遍历循环内,每处理一个品牌就写一次文件,导致数据反复覆盖或重复追加
- 异常处理不完整:部分try块仅捕获异常但未给对应列表添加默认值,导致各列表长度不一致,最终数据错位
- offers数据格式错误:直接将BeautifulSoup对象加入列表,未提取文本,且异常分支未添加默认值
具体修复步骤
- 每次爬取新页面时,清空
productlink列表,避免积累旧链接 - 调整品牌信息获取逻辑,在遍历商品列表时同步收集品牌,确保品牌与商品一一对应
- 将CSV写入操作移到所有数据爬取完成之后,仅执行一次
- 修复
offers的获取逻辑,提取文本内容,并在异常时添加默认值 - 完善所有
try-except块,确保每个异常分支都往对应列表追加默认值,保证各列表长度一致
修正后的完整代码
import requests from bs4 import BeautifulSoup import csv from itertools import zip_longest base_url = 'https://niceonesa.com/ar/' headers = { 'User-Argent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' } # 每页爬取前初始化所有数据列表,避免残留旧数据 for x in range(1, 2): productlink = [] titles = [] brands = [] prices = [] offers = [] rates = [] rate_starts = [] # 获取商品列表页 r = requests.get(f'{base_url}appcomponent--best-sales/?page={x}') soup = BeautifulSoup(r.content, 'lxml') productlist = soup.find_all('div', class_='product-container bg-white rounded-lg') # 同步收集商品链接和品牌信息 for item in productlist: # 每个商品只取第一个有效链接,避免重复 link = item.find('a', href=True) if link: productlink.append(base_url + link['href']) # 收集品牌信息 try: brand = item.find('h3', class_='brand-product mb-1').text.strip() brands.append(brand) except: brands.append('non') # 遍历商品链接爬取详情页 for link in productlink: r = requests.get(link, headers=headers) soup = BeautifulSoup(r.content, 'lxml') # 商品标题 try: title = soup.find('h1', class_='title').text.strip() titles.append(title) except: titles.append('non') # 原价 try: price = soup.find('h3', class_='preReductionPrice mb-2').text.strip() prices.append(price) except: prices.append('non') # 优惠价 try: offer = soup.find('h3', class_='sellingPrice text-nowrap').text.strip() offers.append(offer) except: offers.append('non') # 评分 try: rate = soup.find('span', class_='num-rating align-review').text.strip() rates.append(rate) except: rates.append('non') # 评分星级(修正原可能错误的选择器) try: rate_start = soup.find('div', class_='stars-rating').text.strip() rate_starts.append(rate_start) except: rate_starts.append('non') # 所有数据收集完成后,一次性写入CSV filelist = [titles, brands, prices, offers, rates, rate_starts, productlink] exported = zip_longest(*filelist) with open('oo.csv', 'w', encoding='utf-8-sig', newline='') as filecsv: wr = csv.writer(filecsv) wr.writerow(['title','brands','price','offer','rate','rate_starts','productlink']) wr.writerows(exported)
额外说明
- 原代码中
rate_start的选择器num-rating start可能有误,这里修正为更合理的stars-rating,可根据实际页面结构调整 - 商品链接收集时改为只取每个商品的第一个链接,避免同一商品多个链接导致重复爬取
- 所有数据列表在每页爬取前重新初始化,确保多页爬取时数据不会交叉污染
内容的提问来源于stack exchange,提问作者ALI ALHARBI
相关产品推荐
相关产品推荐

