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

