Selenium使用if-else为Dataclass赋值时出现重复条目问题
问题:爬取cellphones.com.vn商品时出现重复条目
我正在从cellphones.com.vn抓取商品信息(名称、价格、图片、链接),商品价格有两种格式:一种是越南盾字符串(比如1.000.000₫),另一种是文本Giá Liên Hệ(意为“联系询价”)。我希望遇到Giá Liên Hệ时将价格设为0,但运行代码后返回了重复的商品条目。
我的数据类(考虑将current_price改为Decimal类型)
@dataclass class Item: url: str name: str current_price: str place: str img: str date_add: datetime.datetime
爬虫函数代码
def cellphones(query): lists = [] search = query.replace(' ', '%20') url = f"https://cellphones.com.vn/catalogsearch/result?q={search}" driver.get(url) content = driver.find_element(By.CSS_SELECTOR, "div[id*='search-catalog-page']") items = content.find_elements(By.CSS_SELECTOR, "div[class*='product-info']") for _ in items: if _.find_element(By.CSS_SELECTOR, "p[class*='product__price--show']").text == "Giá Liên Hệ": item = Item( url=_.find_element(By.CSS_SELECTOR, "a").get_attribute('href'), name=_.find_element(By.CSS_SELECTOR, "h3").text, current_price=Decimal("0"), place="Cellphones", img=_.find_element(By.CSS_SELECTOR, "img").get_attribute('src'), date_add=datetime.datetime.now() ) else: item = Item( url=_.find_element(By.CSS_SELECTOR, "a").get_attribute('href'), name=_.find_element(By.CSS_SELECTOR, "h3").text, current_price=Decimal(_.find_element(By.CSS_SELECTOR, "p[class*='product__price--show']").text.replace("₫", "").replace(".","").replace(" ","")), place="Cellphones", img=_.find_element(By.CSS_SELECTOR, "img").get_attribute('src'), date_add=datetime.datetime.now() ) item, created = Product.objects.update_or_create( name=item.name, place=item.place, defaults={ 'current_price': item.current_price, 'url': item.url, 'img': item.img, 'date_add': item.date_add } ) lists.append(item) return lists
模板代码
{% block content %} <p>You searched '<span>{{context.name}}</span>'</p> <p>Return {{lists|length}} products.</p> <ul class="d-flex flex-row flex-wrap align-content-center justify-content-around align-items-center list-unstyled"> {% for p in lists %} <li> <div class="card h-100 mt-2 border-dark mb-3" style="max-width: 18rem;"> <img src="{{p.img}}" class="card-img-top" style="height:17.813em;width:auto;" alt="product image"> <div class="card-body"> <h5 class="card-title">{{p.name}}</h5> {% if p.current_price == 0 %} <p class="card-text">Giá Liên Hệ</p> {% else %} <p class="card-text">{{p.current_price|intcomma}}</p> {% endif %} <p class="card-text">Store: {{p.place}}</p> <p class="card-text">Add at {{p.date_add}}</p> <a href="{{p.url}}" target="_blank" class="btn btn-primary">Go to store</a> </div> </div> </li> {% endfor %} </ul>{% endblock %}
重复条目原因及解决方法
原因
重复条目核心问题在于update_or_create的匹配逻辑:仅用name和place作为唯一标识,同一店铺可能存在名称相同但实际为不同商品的情况(比如同型号不同配置的设备);同时页面渲染可能存在重复元素,导致同一商品被多次处理后加入列表。
解决方案
改用唯一标识匹配
商品的url是全局唯一的,替换name作为update_or_create的匹配键:item, created = Product.objects.update_or_create( url=item.url, place=item.place, defaults={ 'current_price': item.current_price, 'name': item.name, 'img': item.img, 'date_add': item.date_add } )页面元素去重
遍历前先通过url过滤重复的页面元素,避免重复处理:processed_urls = set() unique_items = [] for _ in items: item_url = _.find_element(By.CSS_SELECTOR, "a").get_attribute('href') if item_url not in processed_urls: processed_urls.add(item_url) unique_items.append(_) # 遍历去重后的列表 for _ in unique_items: # 原有商品解析逻辑...修正数据类类型
数据类中current_price声明为str,但实际赋值Decimal,类型不匹配需修正:from decimal import Decimal from dataclasses import dataclass import datetime @dataclass class Item: url: str name: str current_price: Decimal place: str img: str date_add: datetime.datetime模板价格判断优化
由于current_price为Decimal类型,确保模板中判断逻辑兼容:{% if p.current_price == Decimal('0') %} <p class="card-text">Giá Liên Hệ</p> {% else %} <p class="card-text">{{p.current_price|intcomma}}</p> {% endif %}
内容的提问来源于stack exchange,提问作者Dung8466
相关产品推荐
相关产品推荐

