Skip to content

⚡分布式微博爬虫。抓取内容包括微博用户资料、微博信息、评论信息和转发信息。目前专注于微博数据抓取本身,正在快速迭代,欢迎watch跟进,star支持

License

Notifications You must be signed in to change notification settings

vfhky/WeiboSpider

 
 

Repository files navigation

关于本项目 :octocat:

  • 无痛分布式微博爬虫,为微博数据抓取而生,部署简单,人肉文档支持
  • 实现内容包括用户信息、用户主页所有微博、微博搜索、微博评论和微博转发关系抓取等
  • 该项目本来是我们项目组的一个子模块,作用是舆情分析。整个系统比较庞大,我只能开源自己写 的代码部分,并基于此做了大量的修改和改进工作。希望能帮到对微博数据采集有需求的同学,对爬虫进阶 感兴趣的同学也可以看看。该项目从模拟登陆到各个页面的请求从简单页面到复杂页面解析处理和相关的异常处理从单机到分布式迁移都做了大量的工作和反复测试,花了我绝大部分业余的时间。
  • 本项目不会承诺每天能抓到多少数据,因为数据量的大小很大程度上取决于用户可用微博账户的数量
  • 与该项目类似的项目大概有SinaSpider,weibo_terminater。 前者是一个基于scrapy的项目,爬的是移动版微博用户信息,质量还不错;后者嘛,还是留给用户 自己判断吧。

你可以用它来干嘛 🈶

  • 爬虫进阶学习,对于需要学习Python进阶和爬虫的同学来说,都可以读读源码
  • 微博舆情分析,比如热门微博转发分析
  • 微博数据分析,比如基于微博用户信息的分析
  • 论文撰写的一些数据,本项目会将抓到的所有数据不定时公布(由于资源所限,暂时只有8.2w条微博用户数据
  • 自然语言处理的语料

为何选择本项目 ⭐

  • 功能全面:包括了用户信息抓取、指定关键字搜索结果增量抓取、指定用户主页所有微博抓取、评论抓取和转发关系抓取等
  • 数据全面:PC端展现的数据量比移动端更加丰富。并且相比于其它同类项目对微博的简单分析,本项目做了大量细致的工作, 比如不同domain不同用户的解析策略、不同domain不同用户的主页分析策略等
  • 稳定!项目可以长期稳定运行。
    • 为了保证程序能长期稳定运行,数据所有的网络请求都是通过抓包手动分析的,未用任何自动化工具, 包括模拟登陆!从另一个方面来说,速度也是比较有保证的(主要还是看账号)
    • 通过合理的阈值设定,账号可以保证安全
    • 即使账号不可用或者登陆失败,项目都对其做了处理(智能冻结账号,出错重试等),以保证每次请求都是有效的,并及时把错误反馈给用户
    • 通过大量的异常检测和处理,几乎捕获了所有的解析和抓取异常。编写了大量的解析代码来获取足够全面的信息
  • 复用性和二次开发性很好。项目很多地方都有详细的代码注释,方便阅读。即使本项目不能完全满足你 对微博数据采集和分析的需求,你也可以自己在该项目的基础上做二次开发,项目已经在微博抓取和各个 模版解析上做了大量工作。
  • 由于本项目与本人实际工作挂钩,所以可以放心它会长期更新。目前已经迭代近一年了。

TODO 🎯

  • 微博内容抓取相关

    • 模拟登陆,账号请放置在sql文件login_info表中
    • 微博常见用户和企业用户信息抓取:通过粉丝和关注进行增量式抓取,起始种子参见sql文件seed_ids
    • 微博搜索功能,搜索词由自己指定,参考sql文件keywords
    • 指定用户的主页:主要是微博内容,目前指定用户是基于已有的seed_ids表中的用户,你也可以指定你想抓取的用户。
    • 指定微博的评论:主要是热门微博,可以由自己指定(正在开发)
    • 指定微博的转发情况:主要是热门微博
  • 反爬虫相关

    • 测试单机单账号访问阈值
    • 测试单机多账号访问效果
    • 验证不同模块,微博系统的容忍度是否相同
    • 验证UA头使用百度、Google等搜索引擎的时候请求是否放宽了:先通过寻找哪些内容是不用 登录就能查看的,这一点主要是从移动端找,因为PC端限制更加严格,然后伪装UA测试请求量。在这个 基础上再使用登录的账号测试
    • 验证登录状态的cookies和代理ip是否可以成功抓取:测试结果是可以使用登录后的cookie 从别的地方进行数据采集,根据这一点,可以考虑使用代理IP,但是代理IP的质量和稳定性可能会 有问题,可能需要找一个或者自己写一个高可用的代理池,这一点还有待考察)
    • 验证移动端登录cookie和pc端是否可共享,如果可以共享则为PC端大规模抓取提供了可能,因为基于 移动端的异地模拟登陆难度比PC端要小
    • 比较单IP和单账号哪个的限制更多,从而制定更加高效的数据采集方案:测试得知,经常是 账号被封了,然后同一个IP用别的账号还能登陆,所以账号的限制比IP更加严格
  • 其它

    • 已有代码修改:将存储后端从Oracle转向Mysql
    • 优化代码,让程序运行更加快速和稳定:水平有限,已经优化过一次了。下一次可能 要等一段时间了
    • 修复某些时候抓取失败的问题(已添加重试机制)
    • 改成分布式爬虫(使用celery做分布式任务调度和管理)
    • 完善文档,包括注明python版本,怎么快速创建虚拟环境,怎么安装相关依赖库;讲解celery 的基本概念和用法,为不会python的同学提供使用的可能性;讲解微博的反爬虫策略;各个tasks模块的作用 和使用方法
    • 完善代码注释,方便用户做二次开发
    • 支持Dockerfile部署项目
    • 支持单个任务执行单机或者多机,在执行单个任务(比如分析指定微博的传播)的时候使用进度条
    • 可视化展示某条微博具体传播信息,微博用户信息等。这个优先级会比较低,目前重点 解决数据抓取和复杂页面解析的问题

项目结构 🔔

  • 功能模块
  • 微博模拟登陆任务 login.py
  • 微博用户抓取任务 user.py
  • 微博特定话题搜索任务 search.py
  • 微博用户主页信息抓取任务 home.py
    config/
        sql/
            spider.sql  # 项目所用表
    db/
        __init__.py
        basic_db.py # 数据库元操作
        login_info.py # 微博账号管理操作
        models.py # sqlalchemy中用到的models
        redis_db.py # redis相关操作,比如管理cookies和urls
        seed_ids.py # 种子用户id管理操作
        user.py # 用户相关操作
    decorator/
        __init__.py
        decorators.py # 项目中用到的装饰器,比如处理超时和模版解析异常
    logger/
        __init__.py
        log.py        # 日志操作
    logs/             # 该目录用于存放日志文件
    page_get/
        __init__.py
        basic.py      # 基本的数据抓取操作
        user.py       # 微博用户抓取
    page_parse/
        user/
            __init__.py
            enterprise.py # 解析服务号
            person.py     # 解析个人用户
            public.py     # 公共模版解析
    tasks/
        __init__.py
        workers.py        # celery worker
        login.py          # 模拟登陆相关任务
        user.py           # 用户抓取相关任务
    tests/                # 一些解析模版,没多少用
    utils/                # 工具类
    wblogin/
        __init__.py
        login.py          # 微博模拟登陆具体实现
    headers.py            # 请求头,主要是UA
    login_first.py        # 由于celery的定时器会有一定时间的间隔,所以第一次需要手动登陆
    test_wbspider.py      # 没什么用的单元测试
    requirements.txt      # 项目相关依赖

有的文件和模块在项目代码中存在,却没有在项目结构中呈现,那么就说明该模块或者该文件还未进行 修改(oracle=>mysql)或者稳定性测试,实现并且测试完成后会补充

配置和使用 ✨

  • 考虑到Python3是趋势和一些用于学习的用户,项目运行环境为Python3.x

  • 项目存储后端使用mysql,所以需要在存储服务器上安装mysql

  • 由于项目是使用celery做分布式任务调度,所以 需要使用broker和各个分布式节点通信,项目使用的是redis,所以需要先安装redis。 注意修改redis的配置文件让它能监听除本机外的别的节点的请求,建议给redis设置密码,如 果没设置密码,需要关闭保护模式(不推荐,这个有安全风险)才能和各个节点通信。如果害怕遇到redis单点 故障,可以使用redis主从配置。

  • 由于高版本的celery不支持windows,所以请在类Unix系统部署。如果实在需要在windows 上部署的话,可以把celery版本降为3.1.25: pip install celery==3.1.25,这是 celery最后支持的一个windows版本;特别注意,windows平台上celery的定时功能不可用! 所以如果需要用到定时任务分发的话,请务必将beat部署到linux或者mac上

  • 安装相关依赖pip install -r requirements.txt

  • 打开配置文件修改数据库和微博账号相关配置

  • 打开sql文件查看并使用建表语句

  • 入口文件:如果有同学有修改源码的需求,那么建议从入口文件开始阅读

  • login.pylogin_first.py:PC端微博登陆程序

  • user.pyuser_first.py:微博用户抓取程序

  • search.pysearch_first.py:微博话题搜索程序

  • home.pyhome_first.py:微博用户主页所有微博抓取程序

  • 微博登录和数据采集

  • 下面说明该项目分布式抓取的基本概念和用法

    • 项目使用了任务路由, 在tasks/workers中可以查看所有的queue,所以需要在启动 worker的时候指定分布式节点的queue,这个queue的作用就是规定该节点能接什么任务,不会接什么任务。比如我的节点1需要做登录任务和用户信息抓取任务,那么我就 需要在节点1指定登录任务的queuelogin_queue和抓取用户信息的queueuser_crawler, 这里启动worker的语句就应该是celery -A tasks.workers -Q login_queue,user_crawler worker -l info --concurrency=1 -Ofair。这样节点1 就只会执行模拟登陆用户信息的相关任务。这样做的好处是:某些任务耗时比较多,就需要更多节点执行,有的耗时小,就不需要这么多节点,比如用户抓取,一个http请求 只能得到一个用户信息,而对于用户关注和粉丝抓取,一个http请求可以得到几十个关注或者粉丝用户的uid。然后再说说各个启动参数的意思:-A指定celery app为 tasks.workers, -Q指定节点1能接受的任务队列是login_queueuser_crawler,即使你对它发送抓取用户粉丝 和用户关注的任务(这个任务在该项目中的queue是fans_followers,在tasks.workers中可查看),它也不会执行。-l表示的是日志等级, --concurrency是worker的线程数,这里规定为1,celery默认采用多线程的方式实现并发,我们也可以让它使用 基于异步IO的方式实现并发,具体参考Celery Concurrency, -Ofair```是避免让celery发生死锁。启动worker的语句需要切换到项目根目录下执行。关于celery更为详细的 知识请参考celery的任务路由说明。项目中使用的所有queue和它们的 作用参见WeiboSpider中的所有任务及其说明和使用

    • 如果是第一次运行该项目,为了让抓取任务能马上执行,需要在任意一个节点上,切换到项目根目录执行python login_first.py获取首次登陆的cookie,需要注意它只会分发任务到指定了login_queue的节点上

    • 在其中一个分布式节点上,切换到项目根目录,再启动beat任务(beat只启动一个,否则会重复执行定时任务): celery beat -A tasks.workers -l info,因为beat任务会有一段时间的延迟(比如登录任务会延迟10个小时再执行),所以通过python login_first.py来获取worker 首次运行需要的cookie是必须的

    • 通过flower监控节点健康状况:先在任意一个节点,切换到项目根目录,再执行flower -A tasks.workers,通过'http://xxxx:5555' 访问所有节点信息,这里的xxxx指的是节点的IP

  • 定时登录是为了维护cookie的时效性,据我实验,微博的cookie有效时长为24小时,因此设置定时执行登录的任务频率必须小于24小时,该项目默认10小时就定时登录一次。

  • 为了保证cookie的可用性,除了做定时登录以外(可能项目代码有未知的bug),另外也从redis层面将cookie过期时间设置为23小时,每次更新cookie就重设过期时间

  • 如果读了上述配置说明还不能顺利运行或者运行该项目的时候出了任何问题,欢迎提issue或者添加我微信(微信号:wpm_wx)询问

常见问题 ❓

  1. 问:项目部署好复杂啊,我可以单机而不是单节点运行吗? 答:可以通过单机运行,单机运行的话,需要对代码做少许修改。主要修改方法是找到你需要的功能的 入口文件,然后跟着改,需要改的地方是@app.task这些函数的代码。以登录为例,如果需要 单机登录的话,那么就先到login模块中把send_task()这条语句 去掉,直接改成调用login_task()函数即可。这里send_task()是网络调用,修改 后就成了本地调用了

  2. 关于redis的问题:为什么我在给redis设置密码后,并且把redis设置成了守护进程,但是没起作用? 答:其实这个问题和项目关系不是特别大吧。。。不过考虑到有的同学并不熟悉redis,我这里还是阐明一下, 如果在linux上面搭redis的话,当我们修改了redis.conf文件后,我们在启动redis的时候也需要指定redis.conf 文件,启动之前,最好把redis-server加入到环境变量中。比如我的redis.conf放在/etc/redis中, 那么我可以通过先切换到/etc/redis目录,再通过redis-server redis.conf来启动redis server,也可以 直接redis-server /etc/redis/redis.conf来启动,前提是 redis-server文件需要在环境变量中

  3. 这个项目的模拟登陆和抓取的时候是怎么处理验证码的啊? 答:这个项目并没有处理验证码,如果要从工程化的角度来解决微博的验证码的问题,研发成本太高了。但是可以通过一些打码平台,来 解决验证码问题。我们现在做的和要做的工作是如何规避验证码,比如模拟登陆的时候尽量在账号常用地登录,还有一个点就是测试微博 的容忍边界,小于它的阈值做采集就不容易被封(不过速度很慢),毕竟按规矩来被封的风险要小得多。如果有图形图像识别的牛人解决了 验证码的问题,欢迎提PR,帮助更多人。

  4. 这个项目能在windows上执行吗? 答:window上可以执行worker节点,beat节点是不可以的,因为windows不支持crontab。如果要混用windows和linux,那么一定 要将celery版本降级为3.1.25。虽然celery4和celery3都可以同时跑,但是这样做flower是没法同时监控两个版本的worker的。

  5. 这个项目一天能抓多少数据? 答:这个实在是没办法保证。数据量由你的账号和分布式节点数量决定的,最关键的是账号数量,目前我6个账号,4个节点,每天抓取量大概 2w条,如果需要更快,那么更多的账号是必不可少的。所以用户需要在速度和稳定性上做一些考量。

  6. 这个项目解析模块为什么用bs而不用xpath,会不会性能很差? 答:项目在一年半以前开始启动,那时候还没接触到xpath,所以选了bs。但是本项目的瓶颈并不在解析模块上,解析再快,还是会被IO请求 所拖累,因为微博服务端对相同cookie的一个时间段的访问次数有限制,并且bs的解析速度也不算慢了。

其它问题暂时还没发现,如果有朋友在使用中遇到问题,欢迎提issue或者直接加我微信询问,我看到的话都会回答的。

其它说明 ❗

  • 本项目运行环境是Python3.x,由于Py2和Py3关于字符编码完全不同,所以如果需要在Py2上运行该程序,需要修改解析模块的相关代码
  • 建议使用linux或者mac作为worker节点,windows平台也可以作为worker节点,但是一定不能作为beat节点,并且celery版本要注意一致。
  • 在运行项目之前,需要在数据库中建表,建表语句参见sql表,也需要把自己的多个微博账号存入表(weibo.login_info)中,把 搜索关键词存入关键词表(keywords)中。这里我已经预插入用户抓取用的一些种子用户了,如果想抓别的用户,请在种子用户表(seed_ids)中做插入操作。
  • 目前该项目已经抓取将近十万条微博用户数据,如果有需要数据的同学,可以开issue。我是打算数据量大了过后再进行分享。
  • 本项目目前默认采用单线程进行抓取,因为多线程和协程等方式抓取会极大增加封号的危险,只能 在速度和稳定性之间进行取舍。可能在尝试代理IP有效性后弄清楚了微博的反爬虫策略后,可能会采 用多线程(也可能采用非阻塞IO)。目前只能通过分布式的方式来提高抓取速度,分布式目前已经可用,所以具有较强的横向扩展性。
  • 如果不需要登录的模块建议就别使用cookie进行抓取,因为这样账号的负载更小。至于哪些信息不需要登录,且是有价值的,这个还会再进行调研,和等待用户的反馈。
  • 如果是开发版,可能会存在运行出问题的情况,所以建议通过release页面下载稳定版
  • 文档方面,考虑到该项目的受众包括不会Python而单纯想拿微博数据的同学和一些想学爬虫进阶的同学,等项目功能完成差不多了, 我会写一个比较详细的使用文档和开发文档。目前在WiKi中 有一些零散的知识点,在本页有关于该项目的使用方法。如果仍然会遇到问题,可以给该项目提issue,也可以加我微信交流,提供人肉文档支持。我的微信号是 wpm_wx,添加的时候请备注微博爬虫
  • 项目由于目前是一个人开发的(估计吃瓜群众积极提PR),所以速度比较慢,目前我只会关注自己会用到或者觉得有趣的部分,有别的 需求的朋友可以提feture,如果恰巧也懂Python,欢迎提PR
  • 如果试用了本项目,觉得项目还不错的,麻烦多多宣传啦。觉得项目太渣或是大家有一些有意义、有趣的想法,欢迎 拍砖、吐槽或者提PR,作者接受一切有意义的建议和提问。另外,随手点个star也是对本人工作的肯定和鼓励:kissing_heart:, 作者也接受捐赠:laughing:。送人玫瑰,手有余香:blush:。

如何贡献 📢

  • 如果遇到使用中有什么问题,可以在issue中提出来
  • 代码中如果有逻辑不合理或者内容不完善的地方,可以fork后进行修改,然后Pull Request,如果一经采纳,就会将你加入contributors
  • 欢迎在issue中提有意义的future
  • 希望有仔细研究过微博反爬虫策略的同学积极提建议

点击查看贡献者名单

一点想法 😆

  • 目前我有一个比较有趣的想法:我也加了一个QQ群,是关于微博爬虫数据抓取的。看群里很多时候都有 同学在求微博数据,包括用户信息数据、微博数据、评论数据、用户主页微博等等,各种各样的数据。由于 微博限制得比较严格,单人想获取千万级甚至亿级的数据,需要特别大的成本,主要是账号的成本,那么为何 不把数据放共享呢?由于本项目是一个分布式的爬虫程序,所以对数据有要求的同学只需要在自己的服务器或者 本机上跑该程序,把抓取的结果放在一个大家都可以用的地方,人多力量大,采集量自然就多,这样也方便 了自己,方便了别人。并且使用者可以只用自己的worker节点执行自己关心的数据的抓取任务。当然这也有一些问题, 最主要的就是数据如何保护,不会被别人恶意破坏。这个目前只是一个想法,如果反馈比较热烈,可能在功能都实现 得差不多了,会搞这么一个东西,想起来还是比较有意思。

赞助本项目:thumbsup:

如果本项目对你有用,欢迎对本项目进行捐赠,捐赠时候请留下你的github ID,当然您也可以匿名捐赠。

致谢:heart:

  • 感谢大神Askcelery分布式任务调度框架
  • 感谢大神kennethreitzrequests
  • 感谢网友 李* 和 西*弗斯 热心测试和提供建议
  • 感谢网友 sKeletOn、frankfff 捐赠,所有捐款都会贡献部分(20%)给celery,用以支持和鼓励其发展! 而requests未提供donate方式,所以目前只能通过saythanks.io对其表示谢意。

About

⚡分布式微博爬虫。抓取内容包括微博用户资料、微博信息、评论信息和转发信息。目前专注于微博数据抓取本身,正在快速迭代,欢迎watch跟进,star支持

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 100.0%