V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
zyy1245367562
V2EX  ›  Python

scrapy 中使用 MongoDB 数据库存储抓取到的 IP,判断新抓的 IP 在数据库中是否已经存在,如果存在则不再添加,不存在则插入这条数据,但是执行结果总是不对?

  •  
  •   zyy1245367562 · 2017-12-03 13:47:11 +08:00 · 3537 次点击
    这是一个创建于 2540 天前的主题,其中的信息可能已经有所发展或是发生改变。
    pipelines.py 中的关键代码为:
    if db.mycollection.find({"ip":item["ip"]}):
    print "{} has already existed.".format(item["ip"])
    print db.mycollection.find()
    else:
    db.mycollection.insert_one(data)
    print db.mycollection.count({})
    执行的结果总是:
    120.25.164.134 has already existed.
    <pymongo.cursor.Cursor object at 0x0000000005B330F0>
    ……
    提示我抓取到的每一条数据都是存在的,我的 mycollection 聚集中最开始是空的,为什么会出现这种情况呢?
    14 条回复    2017-12-06 09:03:17 +08:00
    zyy1245367562
        1
    zyy1245367562  
    OP
       2017-12-03 14:48:52 +08:00
    怎么没有前辈来指教一下呢?
    tosexxx
        2
    tosexxx  
       2017-12-03 15:09:52 +08:00
    大佬都在度假,没空 8 小时之外看 v 站
    SO647898
        3
    SO647898  
       2017-12-03 15:16:03 +08:00 via Android
    大佬都在度假,没空 8 小时之外看 v 站
    kenzh
        4
    kenzh  
       2017-12-03 15:27:51 +08:00   ❤️ 1
    看了下文档,find()总是返回的是 Cursor, 猜测应该用 db.mycollection.find({"ip":item["ip"]}).count() 吧。
    golmic
        5
    golmic  
       2017-12-03 15:29:52 +08:00 via Android
    用 upsert
    swulling
        6
    swulling  
       2017-12-03 16:19:44 +08:00 via iPad
    brickyang
        7
    brickyang  
       2017-12-03 19:38:17 +08:00 via iPhone   ❤️ 1
    .find() 返回的是 cursor,用 find().toArray() 返回的是查找结果的数组,如果不存在就是个空数组。

    你也可以试试 .findOneAndUpdate() 并设置 upsert: true,这样如果找到记录则更新(更新内容为空),找不到则新建一条记录。
    fds
        8
    fds  
       2017-12-03 20:00:39 +08:00   ❤️ 1
    返回的是 cursor,肯定为 True 呀,你得调用.next()才可能获得一个空结果吧。
    另外,这种约束条件一般是这样实现:在 ip 上建立一个 unique 的索引,然后每次都直接插入;如果已有,则会报错 duplicate,忽略即可。你这种 ifelse 不是“原子”操作,如果有多个进程同时工作,可能插入多条相同 ip 的。
    livexia
        9
    livexia  
       2017-12-03 21:32:11 +08:00
    find_one
    lihongjie0209
        10
    lihongjie0209  
       2017-12-03 21:38:37 +08:00   ❤️ 1
    动态语言就是有这个问题
    如果你需要集合为空:
    那么使用 if collection.isEmpty 或者是 if collection.size() == 0

    如果你需要集合为 null/none:
    那么使用 if collection== null/none

    这样写代码的时候意图清楚, 看代码的人也轻松.
    zyy1245367562
        11
    zyy1245367562  
    OP
       2017-12-05 19:26:28 +08:00
    @kenzh 你的建议可以实现。谢谢。
    zyy1245367562
        12
    zyy1245367562  
    OP
       2017-12-05 19:29:16 +08:00
    @fds 嗯,你说的对,这一点确实没有考虑到。
    zyy1245367562
        13
    zyy1245367562  
    OP
       2017-12-05 19:30:01 +08:00
    @lihongjie0209 嗯,受教了。谢谢前辈。
    toono
        14
    toono  
       2017-12-06 09:03:17 +08:00
    find 方法返回的都是集合对象。

    下面我的实际代码,是需要先把查询回来的结果对象使用 count 方法去查看具体数量

    def process_item(self, item, spider):
    result = self.db[self.mongo_collection].find({'source_url': item['source_url']})
    if result.count() != 0:
    raise DropItem("Duplicate item found: %s" % item)
    else:
    return item
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2845 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 14:45 · PVG 22:45 · LAX 06:45 · JFK 09:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.