手撕包菜磁力搜索引擎的开源说明

已经一年半载没有写博客了,搞得上来不知道写些什么。博客上的内容还时不时有人评论,大部分我还是会一一回复的。有些人会关注我的博客用什么主机,我的博客现在是用Linode的主机,因为现在很便宜,而且配置不差。另外比较多的是问手撕包菜的源代码能否提供,能否出售。今天我写这个文章就是把手撕包菜的网站开源了,包括网站页面,DHT爬虫和搜索引擎相关部分。

2年前的那篇跟磁力搜索相关的文章在这里:
写了个磁力搜索的网页 - 收录最近热门分享的资源

作为最早在国内研究和实践DHT爬虫的人,我的灵感是来自芬兰Helsinki大学的这篇论文:
Real-World Sybil Attacks in BitTorrent Mainline DHT

英文好的同学应该很容易读懂,跟我写的不到300行的爬虫代码大致原理一样。初次接触DHT网络的可以结合我之前的文章阅读,或者拜读Kevin Lynx的博客。所以具体原理在这里就不再阐述了。

手撕包菜一开始只是为了纯粹的技术研究,没有去想这个搜索引擎能给网民带来什么样的福利。当时采集了大量的数据,发现有一半以上的资源为限级内容,于是试图去对资源进行分类并且做了很多这方面的工作。譬如,基本上能通过一套规则能筛选出限级内容,对资源进行分类,如果是视频还能匹配出是哪一部影片。可惜,这些工作我主观上认为对生活应用并没有太大价值,于是就放弃了深入的研究。或许是因为网民使用此类搜索引擎大部分都是具有明显的目的性。

手撕包菜经历了多次点技术变更。开源版本使用了django网站框架重写,之前是Flask,再早期是tornado。电影FM也是使用tornado,后来发现tornado并不适用于任何场景。以内容为王的网站还是django比较擅长,只是入门时间比其他框架都较长。早期数据库采用了MongoDB,因为配合Python读写数据很方便,也不用关注数据结构,搜索功能采用自带的关键词搜索,不过后来随着资源数量增加,性能也明显跟不上。今年换了WiredTiger引擎,自带的fulltext search还是不给力。另外Amazon的cloudsearch是个坑,土豪可以考虑,性能真的很不错,就是比较贵。最后还是搭建一个SphinxSearch吧,数据库也换成MySQL(MyISAM引擎),配合起来也很方便。Sphinx创建全文索引的速度很给力,官方的自评也很高,我自己测试1000w的资源(大概3GB),1分钟左右就索引完毕。不信,大家可以自测一下。

网站和爬虫代码已经上传到GitHub,地址:

https://github.com/78/ssbc

代码采用GPLv2协议发布,使用时请遵循GPLv2的规定。
开源的目的是为了交流,学习和改进。如果商用,请务必告知。

附一个P2P网络协议QQ交流群:97912038。

手撕包菜磁力搜索引擎的开源说明》上有133条评论

    1. testshell

      announce_peer获得info_hash后,转换为对应的磁力链接,utorrent下载种子失败, 这是怎么回事。
      utorrent开启了DHT。 用libtorrent把announce_peer的节点加入到router中,下载也会失败。

      回复
  1. 老太太

    先fork先, 怕你删了, 我对你Django使用方式感兴趣. 当然, 使用libtorrent来下载种子, 不是个好方式, 因为这家伙太难装了, 至少我从来没安装成功过.

    我自己实现了从DHT下载metadata, 效果非常不错, 一开始, 8M/s, 每天爬取100W左右. DHT那部分, 个人认为, 没我写得漂亮.

    :)

    回复
          1. 合作共赢

            你好,你的代码我已收到,但是我对你的网站有意。希望能购买并亲自运营。你这边再帮忙负责一年内的网站技术方面的支持!

            回复
      1. 天天向上

        博主,如何安装呀,由于对python不太熟悉,还望求一份简单的教程,本人邮箱:1203561895@qq.com,十分感谢

        回复
    1. ibin

      我也是小白,能有个教程最好,
      不过,我不想做磁力链

      就想做个定向爬取一个网站,然后把内容展现我的网站,不知道python做这个应该是

      很轻松吧

      回复
    1. Xiaoxia 文章作者

      我的系统是centos7,安装epel-release包后,大部分依赖的都能安装。你需要使用virtualenv来建立python运行环境。日后有空我再补充教程吧

      回复
      1. Jennr

        今天新安装了centos 7 ,然后基本是使用依赖安装的。

        装完后启动还是遇到了一些问题。
        第一个问题是运行meta_worker.py时提醒缺少包libtorrent

        python meta_worker.py
        Traceback (most recent call last):
        File "meta_worker.py", line 28, in
        import libtorrent as lt
        ImportError: No module named libtorrent

        第二个问题是运行 manage.py 时报错了。

        python manage.py runserver
        Performing system checks...

        Unhandled exception in thread started by
        Traceback (most recent call last):
        File "/home/job/ssbc/lib/python2.7/site-packages/django/utils/autoreload.py", line 223, in wrapper
        fn(*args, **kwargs)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 110, in inner_run
        self.validate(display_num_errors=True)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/core/management/base.py", line 465, in validate
        return self.check(app_configs=app_configs, display_num_errors=display_num_errors)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/core/management/base.py", line 478, in check
        include_deployment_checks=include_deployment_checks,
        File "/home/job/ssbc/lib/python2.7/site-packages/django/core/checks/registry.py", line 72, in run_checks
        new_errors = check(app_configs=app_configs)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/core/checks/model_checks.py", line 28, in check_all_models
        errors.extend(model.check(**kwargs))
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/models/base.py", line 1181, in check
        errors.extend(cls._check_fields(**kwargs))
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/models/base.py", line 1258, in _check_fields
        errors.extend(field.check(**kwargs))
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 934, in check
        errors = super(AutoField, self).check(**kwargs)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 207, in check
        errors.extend(self._check_backend_specific_checks(**kwargs))
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 306, in _check_backend_specific_checks
        return connection.validation.check_field(self, **kwargs)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/mysql/validation.py", line 18, in check_field
        field_type = field.db_type(connection)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 614, in db_type
        return connection.data_types[self.get_internal_type()] % data
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/__init__.py", line 36, in __getattr__
        return getattr(connections[DEFAULT_DB_ALIAS], item)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/utils/functional.py", line 60, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 196, in data_types
        if self.features.supports_microsecond_precision:
        File "/home/job/ssbc/lib/python2.7/site-packages/django/utils/functional.py", line 60, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/mysql/features.py", line 52, in supports_microsecond_precision
        return self.connection.mysql_version >= (5, 6, 4) and Database.version_info >= (1, 2, 5)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/utils/functional.py", line 60, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 371, in mysql_version
        with self.temporary_connection():
        File "/usr/lib64/python2.7/contextlib.py", line 17, in __enter__
        return self.gen.next()
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/base/base.py", line 462, in temporary_connection
        cursor = self.cursor()
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/base/base.py", line 164, in cursor
        cursor = self.make_cursor(self._cursor())
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/base/base.py", line 135, in _cursor
        self.ensure_connection()
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/base/base.py", line 130, in ensure_connection
        self.connect()
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/utils.py", line 97, in __exit__
        six.reraise(dj_exc_type, dj_exc_value, traceback)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/base/base.py", line 130, in ensure_connection
        self.connect()
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/base/base.py", line 119, in connect
        self.connection = self.get_new_connection(conn_params)
        File "/home/job/ssbc/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 276, in get_new_connection
        conn = Database.connect(**conn_params)
        File "/home/job/ssbc/lib/python2.7/site-packages/MySQLdb/__init__.py", line 81, in Connect
        return Connection(*args, **kwargs)
        File "/home/job/ssbc/lib/python2.7/site-packages/MySQLdb/connections.py", line 193, in __init__
        super(Connection, self).__init__(*args, **kwargs2)
        django.db.utils.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: NO)")

        期盼小虾的回复。

        回复
        1. Jennr

          第一个问题是没有安装libtorrent,后面已经编译安装了。
          第二个问题是数据库配置信息不对,也已经可以了。

          http://192.241.231.244

          已经安装好,还有两个问题。
          一个是搜索或者点击具体电影,会报错。
          二是爬虫执行时,都是time out,最后都没有抓取到数据。

          另外还有一个问题请教一下。
          如果我python meta_worker.py保持不关闭,这时候再python 任何一个py文件,都是提示ImportError。这是为什么呀。

          回复
        2. Xiaoxia 文章作者

          回答你两个问题:
          1、使用 yum search rb_libtorrent 可以找到安装包
          2、你的mysql装好之后修改了root密码?提示数据库密码不正确。

          回复
  2. jx

    xiaoxia!!!!手撕包菜磁力搜索,我已经下好了,就是不知道如何开打运行看下效果,不知如何做,还请指导!!!

    回复
  3. jianson

    metadata, options = get_config()
    File “setup_posix.py”, line 43, in get_config
    libs = mysql_config(“libs_r”)
    File “setup_posix.py”, line 25, in mysql_config
    raise EnvironmentError(“%s not found” % (mysql_config.path,))
    EnvironmentError: mysql_config not found

    —————————————-
    Command “python setup.py egg_info” failed with error code 1 in /private/tmp/pip-build-6fnzg5/MySQL-python

    回复
    1. 一零八八

      运行supervisord -c super.conf
      提示Error: .ini file does not include supervisord section
      For help, use /home/job/ssbc/bin/supervisord -h

      回复
  4. 小粥

    终于开源了,特来感谢一下,最近需要用到dht网络获取种子,正好敢上作者开源,下载学习一下。

    回复
    1. xfshi

      能给个搭建教程吗,我运行python manage.py make migrations,报错如下:
      Traceback (most recent call last):
      File “manage.py”, line 10, in
      execute_from_command_line(sys.argv)
      File “/usr/lib/python2.7/site-packages/django/core/management/__init__.py”, line 338, in execute_from_command_line
      utility.execute()
      File “/usr/lib/python2.7/site-packages/django/core/management/__init__.py”, line 312, in execute
      django.setup()
      File “/usr/lib/python2.7/site-packages/django/__init__.py”, line 18, in setup
      apps.populate(settings.INSTALLED_APPS)
      File “/usr/lib/python2.7/site-packages/django/apps/registry.py”, line 108, in populate
      app_config.import_models(all_models)
      File “/usr/lib/python2.7/site-packages/django/apps/config.py”, line 198, in import_models
      self.models_module = import_module(models_module_name)
      File “/usr/lib64/python2.7/importlib/__init__.py”, line 37, in import_module
      __import__(name)
      File “/root/ssbc-master/search/models.py”, line 13, in
      search_conn = mdb.connect(‘127.0.0.1′, ‘root’, ”, ”, port=9306, charset=’utf8′, cursorclass=MySQLdb.cursors.DictCursor)
      File “/usr/lib64/python2.7/site-packages/MySQLdb/__init__.py”, line 81, in Connect
      return Connection(*args, **kwargs)
      File “/usr/lib64/python2.7/site-packages/MySQLdb/connections.py”, line 193, in __init__
      super(Connection, self).__init__(*args, **kwargs2)
      _mysql_exceptions.OperationalError: (2003, “Can’t connect to MySQL server on ‘127.0.0.1’ (111)”)

      回复
  5. daniel

    你好, 有个问题请教一下, 我修改好sphinx.conf 之后, 执行
    sudo indexer -c sphinx.conf –all
    报错:
    skipping non-plain index ‘rt_main’…
    可以帮忙看一下么? 谢谢

    回复
  6. Pingback引用通告: 磁力搜索开源程序:手撕包菜 | 福利Bar

  7. 颜沫

    你好!请问下有这个的安装教程吗。。。。因为我是小白对这安装不懂哎,能不能请教下

    回复
  8. Peter

    [root@default workers]# python meta_worker.py python meta_worker.py
    Thread-39 started
    Traceback (most recent call last):
    File “meta_worker.py”, line 286, in
    reporter = DHTReporter()
    File “meta_worker.py”, line 48, in __init__
    self.ses = lt.session()
    RuntimeError: epoll: Too many open files

    [root@default workers]# python meta_worker.py python meta_worker.py
    Thread-39 started
    Traceback (most recent call last):
    File “meta_worker.py”, line 286, in
    File “meta_worker.py”, line 48, in __init__
    RuntimeError: eventfd_select_interrupter: Too many open files

    回复
  9. mich

    博主,求教!

    1. 磁力链接 是 如何转成种子的??
    2. 需要把所有的种子下载下来才能知道该磁力链接 是视频还是图片文件吗?
    3. DHT协议爬虫,下载种子的时候, 需要用announce_peer 去通知吗??

    回复
  10. jackyspy

    一开始就猜手撕包菜是你的杰作,折腾精神不减啊。
    可以考虑dht爬虫数据共享,分布式爬取后聚合。
    另问,还做QQ协议分析方面的事情吗?现在那些个QQ机器人基于webqq协议的?

    回复
  11. 罐子

    __import__(name) File “/usr/lib/python2.6/site-packages/django/contrib/admin/__init__.py”, line
    3, in
    from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
    File “/usr/lib/python2.6/site-packages/django/contrib/admin/helpers.py”, line
    3, in
    from django.contrib.admin.util import (flatten_fieldsets, lookup_field,
    File “/usr/lib/python2.6/site-packages/django/contrib/admin/util.py”, line 1,
    in
    from django.db import models
    File “/usr/lib/python2.6/site-packages/django/db/__init__.py”, line 78, in
    connection = connections[DEFAULT_DB_ALIAS]
    File “/usr/lib/python2.6/site-packages/django/db/utils.py”, line 93, in __geti
    tem__
    backend = load_backend(db[‘ENGINE’])
    File “/usr/lib/python2.6/site-packages/django/db/utils.py”, line 33, in load_b
    ackend
    return import_module(‘.base’, backend_name)
    File “/usr/lib/python2.6/site-packages/django/utils/importlib.py”, line 35, in
    import_module
    __import__(name)
    File “/usr/lib/python2.6/site-packages/django/db/backends/mysql/base.py”, line
    14, in
    raise ImproperlyConfigured(“Error loading MySQLdb module: %s” % e)
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No mo
    dule named MySQLdb
    You have new mail in /var/spool/mail/root
    [root@host-133-130-59-136 bt]#
    提示这个

    回复
  12. 电影下载

    我不是搞技术的 半路出家 不知道Windows 2003系统能安装吗 xiaoxia你什么时候可以出出一份安装使用教程不 真的太感谢了 很喜欢这套程序

    回复
  13. 我试试

    [root@la workers]# python -u simdht_worker.py
    Thread-1 started

    Saved 6ae6d728ae3e1a24cd2d028e8dd227034f37d322 pt
    Saved 6ae6d728ae3e1a24cd2d028e8dd227034f37d322
    Saved 5008d0428fa03752b8ce4c93094c992914031cf2 pt
    Saved 5008d0428fa03752b8ce4c93094c992914031cf2Exception in thread Thread-1:
    Traceback (most recent call last):
    File “/usr/local/python2.7/lib/python2.7/threading.py”, line 810, in __bootstrap_inner
    self.run()
    File “simdht_worker.py”, line 374, in run
    t.start()
    File “/usr/local/python2.7/lib/python2.7/threading.py”, line 745, in start
    _start_new_thread(self.__bootstrap, ())
    error: can’t start new thread
    在执行simdht一会后提示这个是什么错误呢?

    回复
      1. 我试试

        UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xa8 in position 8: ordinal not in range(128)
        偶尔还提示这个.

        回复
  14. fans

    xiaoxia,我用的是ubuntu14.04,安装什么的一切正常为什么,执行python simdht_worker.py时,只提示:thread1 started.
    并不下载,怎么办?

    回复
  15. 小雨

    先感谢分享,希望小虾可以出一个使用教程,我这样的菜鸟只能看看 不能使用心里痒痒的

    回复
  16. zoney

    xiaoxia,你好,我用你的源码,网页呈现的时候,分类信息只有其他,能不能指点一下,谢谢

    回复
  17. Pingback引用通告: 磁力搜索引擎 | 个人小站

  18. tim

    磁力搜索用sphinx的几个模式,SPH_MATCH_ALL好,还是SPH_MATCH_ANY好?

    SPH_MATCH_ALL是整个词组匹配,SPH_MATCH_ANY是任意一个词匹配就命中,感觉SPH_MATCH_ANY搜索会出来很多不相关的结果

    没有复杂的词库对应参考,好像还是SPH_MATCH_ALL效果好点?

    回复
  19. 不称

    xia哥,这个一搜索就出错是怎么会事啊?
    报错如下,期待xia哥的答复
    Sorry, an error has occurred: (1046, ‘No database selected’)

    回复
  20. 看到现在的电影FM有标记已看电影功能了,但是没有像豆瓣那样的筛选掉已看电影的功能,如果没有筛选的话,标记的用处和意义大减,有没有可能添加呢?大神

    回复
      1. 也包括搜索,主要是在分类里,比如我点了电影大全里的“喜剧”分类,会出来所有喜剧电影,在这前提下标记并筛选。

        回复
  21. 大帅哥

    Sorry, an error has occurred: (1064, “You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ”\xe5\x8a\xa8\xe9\x9d\x99′) ORDER BY create_time DESC \n LIMIT 0,10\n OPTION m’ at line 1″)
    这个问题怎么解决

    回复
  22. will

    请问如果用mongodb作存储行不行,sphinx对内存要求大吗。有没有mongodb to sphinx的同步方案?
    谢谢

    回复
  23. root

    作者可否优化下爬虫….
    simdht_worker.py 运行一段时间cpu100% 内存也存满了

    然后直接 mysql server has gone away 或者直接不爬了 然后资源降下来

    谢谢

    回复
  24. 啪啪君

    博主,求一份中文模板,自己尝试改了下
    但是有很多字段没找到,希望能给一份早前的中文模板
    谢了!

    回复
  25. hjoker

    我的理解是,用爬虫先收集种子信息,然后提取关键字构建磁力链接与之对应 存到数据库中,这样查的话,模糊搜索直接调用数据库中的信息,不知道这样对不对?

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>