如何提升MongoDB已知ID列表与爬取ID的比对速度?
优化ID比对性能的方案
问题根源
你当前的代码每次处理一个爬取到的ID时,都要遍历MongoDB集合里的所有ID,时间复杂度是O(n*m)(n是爬取的链接数,m是数据库里的ID总数),这是导致耗时过长的核心原因。下面是几个针对性的优化方案:
方案1:把数据库ID预加载到内存集合(最快)
一次性从MongoDB取出所有ID,存入Python的set(哈希集合,查询时间O(1)),之后每次比对直接判断ID是否在集合里,避免反复查询数据库。
修改后的代码:
from pymongo import MongoClient import re from selenium.webdriver.common.by import By client = MongoClient('mongodb://localhost:27017/') mydb = client['db'] mycol = mydb['collection'] if __name__ == '__main__': # 提前加载所有已知ID到set,只执行一次 known_ids = set() # 批量获取所有Id字段 for doc in mycol.find({}, {"Id": 1, "_id": 0}): known_ids.add(doc['Id']) # 后续爬取循环 for item in driver.find_elements(By.XPATH, '//a'): # 注意这里是复数find_elements,原代码可能写错了 url = item.get_attribute('href') myid = re.sub(r'.*item/([0-9a-f-]+)\?.*', r'\1', url) # 直接判断是否存在,O(1)时间 if myid in known_ids: continue # 已存在就跳过 # 这里写处理新ID的逻辑 [...]
方案2:利用MongoDB的单条查询能力
如果数据库里的ID数量极大,内存装不下,可以每次直接让MongoDB查询当前ID是否存在,配合索引能做到O(1)查询。
修改后的代码:
from pymongo import MongoClient import re from selenium.webdriver.common.by import By client = MongoClient('mongodb://localhost:27017/') mydb = client['db'] mycol = mydb['collection'] # 给Id字段加索引(只需要执行一次,之后可以注释掉) mycol.create_index("Id") if __name__ == '__main__': for item in driver.find_elements(By.XPATH, '//a'): url = item.get_attribute('href') myid = re.sub(r'.*item/([0-9a-f-]+)\?.*', r'\1', url) # 直接查询数据库是否存在该ID exists = mycol.find_one({"Id": myid}, {"_id": 1}) is not None if exists: continue # 处理新ID的逻辑 [...]
关键优化点补充
- 给
Id字段加索引:不管用哪种方案,给MongoDB的Id字段创建单字段索引都能大幅提升查询/批量获取的速度,执行一次mycol.create_index("Id")即可。 - 修正原代码小错误:原代码里
driver.find_element是单数,只会返回第一个元素,应该改成driver.find_elements(复数)才能遍历所有链接。
内容的提问来源于stack exchange,提问作者Mévatlavé Kraspek
相关产品推荐
相关产品推荐

