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

Django Scrapy匹配故障:match_maker仅返回4个成员而非预期150个的解决求助

Django Scrapy匹配故障:match_maker仅返回4个成员而非预期150个的解决求助

问题描述

我在做一个Django项目,用Scrapy爬取网站上的用户资料,爬取到的数据交给match_maker方法处理。但现在遇到个头疼的问题:数据库里有153个成员(排除3个staff成员后剩150个普通成员),可match_maker只返回4个匹配结果。

细节

  • 数据库:共153个成员,其中3个是staff,剩余150个为普通成员
  • 资料类型:每个成员的profile_type分为'Man'、'Woman'、'Trans'、'Couple'四种

核心问题

match_maker方法里有个循环用来给成员分配房间,我用used_rooms集合跟踪已分配的房间,确保每个房间只分配一次。相关代码片段是:

if room["username"] in used_rooms:
    continue

当这个条件生效时,方法仅返回4个成员;如果注释掉这个检查,虽然能处理所有150个成员,但可用房间数会飙到一百万以上,这明显不符合预期。

我的目标

我需要实现每个房间只分配给一个成员,同时保证所有150个普通成员都能被正确处理,不会出现重复分配房间的情况。想请教大家怎么解决这个矛盾的问题。

已尝试的操作

  • 验证唯一性:确认每个房间的room["username"]都是唯一的
  • 调试used_rooms:打印集合的前后状态,确认它在正常填充
  • 检查房间数据结构:反复核对所有房间的room["username"]没有重复

但试了这些之后问题还是存在,希望能得到大家的思路和建议。

原代码片段

def match_maker(self, members, room_data: list):
        matched_items = []
        used_rooms = set() # Keep track of assigned rooms
        room_data_copy = deepcopy(room_data)
        
        # Group rooms by profile_type for quick lookup
        rooms_by_type = defaultdict(list)
        
        for room in room_data_copy:
            if len(room["body"]) >= 5:  # Only store rooms with a valid description
                rooms_by_type[room["profile_type"]].append(room)

        users = set()

        for member in members:
            if member.is_staff:
                continue
            
            # Get matching rooms for this profile_type
            available_rooms = rooms_by_type.get(member.profile_type, [])
                        
            for room in available_rooms:
                if room["username"] in used_rooms:
                    continue

                if room["profile_type"] != member.profile_type:
                    continue
                
                users.add(member.username)      
                matched_items.append((member, room))
                used_rooms.add(room["username"])
        
        print(f"The users are: {users}")
        print(f"The number of users are: {len(users)}")
        
        
        random.shuffle(matched_items)
        
        return matched_items

解决方案(来自@Serhii Fomenko)

原代码的问题出在循环逻辑上:遍历每个成员时,一旦找到第一个可用房间就会标记该房间为已使用,但如果某个profile_type的房间数量很少(比如只有4个),前面的成员会把同类型的房间全抢完,后面的同类型成员就找不到可用房间了,最终只匹配到4个成员。

修正后的代码调整了匹配逻辑:先把成员和房间都按profile_type分组,然后对每个类型的房间循环,用循环迭代器轮流分配给同类型的成员,既保证每个房间只分配一次,也能让所有成员都拿到对应的房间。

def match_maker(self, members: QuerySet[Member], room_data: list):
        matched_items = []
        room_data_copy = deepcopy(room_data)
        
        # Group rooms by profile_type for quick lookup
        rooms_by_type: dict = defaultdict(list)
        
        for room in room_data_copy:
            if len(room["body"]) >= 5:  # Only store rooms with a valid description
                rooms_by_type[room["profile_type"]].append(room)
        
        members_by_type = defaultdict(list)
        for member in members:
            if not member.is_staff:
                members_by_type[member.profile_type].append(member)
        
        processed_usernames = set()
        
        for profile_type, members_list in members_by_type.items():
            members_it = cycle(members_list)
            for available_room in rooms_by_type[profile_type]:
                member = next(members_it)
                matched_items.append((member, available_room))
                processed_usernames.add(member.username)
        
        random.shuffle(matched_items)
        
        return matched_items

备注:内容来源于stack exchange,提问作者AJJ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 09:34:31