Python分布式微博爬虫(源码分享)

项目地址:https://github.com/ResolveWang/weibospider 作者:resolvewang

关于本项目

  • 实现内容包括用户信息、用户主页所有微博、微博搜索、微博评论和微博转发关系抓取等
  • 本项目基于本人实际的工作,并对此做了大量的修改和改进。希望能帮到对微博数据采集有需求的同学,对爬虫进阶 感兴趣的同学也可以看看。该项目从模拟登陆到各个页面的请求、从简单页面到复杂页面解析处理和相关的异常处理、 从单机到分布式迁移都做了大量的工作和反复测试,花了我绝大部分业余的时间

你可以用它来干嘛

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

为何选择本项目

  • 功能全面:包括了用户信息抓取、指定关键字搜索结果增量抓取、指定用户主页所有微博抓取、评论抓取和转发关系抓取等
  • 数据全面:PC端展现的数据量比移动端更加丰富。并且相比于其它同类项目对微博的简单分析,本项目做了大量细致的工作, 比如不同 domain 不同用户的解析策略、不同 domain 不同用户的主页分析策略等
  • 稳定!项目可以长期稳定运行。
  • 为了保证程序能长期稳定运行,数据所有的网络请求都是通过抓包手动分析的,未用任何自动化工具, 包括模拟登陆!从另一个方面来说,抓取速度也是比较有保证的(主要还是看账号数量)
  • 通过合理的阈值设定,账号可以保证安全
  • 即使账号不可用或者登陆失败,项目都对其做了处理(智能冻结账号,出错重试等),以保证每次请求都是有效的,并及时把错误反馈给用户
  • 通过大量的异常检测和处理,几乎捕获了所有的解析和抓取异常。编写了大量的解析代码来获取足够全面的信息
  • 复用性和二次开发性很好。项目很多地方都有详细的代码注释,方便阅读。即使本项目不能完全满足你 对微博数据采集和分析的需求,你也可以自己在该项目的基础上做二次开发,项目已经在微博抓取和各个 模版解析上做了大量工作。
  • 由于本项目与本人实际工作有关联(代码并不是工作中使用的代码),所以可以放心它会长期更新。目前已经迭代一年有余了。
  • 丰富文档支持:请点击wiki查看所有文档。如果文档仍然不能解决你的问题,推荐提issue,我们开发者看到后都会积极回答,也可以 通过加QQ群进行交流。注意在群里没事就潜水,有问题就问,开发者会积极回答。
# coding:utf-8
import time
from db import wb_data
from tasks.workers import app
from page_parse import comment
from config import conf
from page_get.basic import get_page
from db.weibo_comment import save_comments

# 起始请求地址
base_url = 'http://weibo.com/aj/v6/comment/big?ajwvr=6&id={}&page={}&__rnd={}'


@app.task(ignore_result=True)
def crawl_comment_by_page(mid, page_num):
    cur_time = int(time.time() * 1000)
    cur_url = base_url.format(mid, page_num, cur_time)
    html = get_page(cur_url, user_verify=False)
    comment_datas = comment.get_comment_list(html, mid)
    save_comments(comment_datas)
    if page_num == 1:
        wb_data.set_weibo_comment_crawled(mid)
    return html


@app.task(ignore_result=True)
def crawl_comment_page(mid):
    limit = conf.get_max_comment_page() + 1
    # 这里为了马上拿到返回结果,采用本地调用的方式
    first_page = crawl_comment_by_page(mid, 1)
    total_page = comment.get_total_page(first_page)

    if total_page < limit:
        limit = total_page + 1

    for page_num in range(2, limit):
        app.send_task('tasks.comment.crawl_comment_by_page', args=(mid, page_num), queue='comment_page_crawler',
                      routing_key='comment_page_info')


@app.task(ignore_result=True)
def excute_comment_task():
    # 只解析了根评论,而未对根评论下的评论进行抓取,如果有需要的同学,可以适当做修改
    weibo_datas = wb_data.get_weibo_comment_not_crawled()
    for weibo_data in weibo_datas:
        app.send_task('tasks.comment.crawl_comment_page', args=(weibo_data.weibo_id,), queue='comment_crawler',
                      routing_key='comment_info')

项目结构

  • 功能模块
  • 微博模拟登陆任务 login.py
  • 微博用户抓取任务 user.py
  • 微博特定话题搜索任务 search.py
  • 微博用户主页信息抓取任务 home.py
  • 微博评论抓取任务 comment.py
  • 微博转发抓取任务 repost.py

配置和使用

  • 环境配置:小白和新手请直接查看这里
  • 考虑到Python3是趋势和一些将该项目用于学习的用户,项目运行环境为Python3.x
  • 项目存储后端使用Mysql,所以需要在存储服务器上安装Mysql,注意设置字符集编码为utf-8
  • 由于项目是使用celery做分布式任务调度,所以 需要使用broker和各个分布式节点通信,项目使用的是Redis,所以需要先安装Redis。 注意修改Redis的配置文件让它能监听除本机外的别的节点的请求,建议给Redis设置密码,如 果没设置密码,需要关闭保护模式(不推荐,这个有安全风险)才能和各个节点通信。如果害怕遇到Redis单点 故障,可以使用Redis主从配置。

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

  • login.py和login_first.py:PC端微博登陆程序
  • user.py和user_first.py:微博用户抓取程序
  • search.py和search_first.py:微博话题搜索程序
  • home.py和home_first.py:微博用户主页所有微博抓取程序
  • comment.py和comment_first.py:微博评论抓取
  • repost.py和repost_first.py:转发信息抓取
# coding:utf-8
import time
from logger.log import crawler
from tasks.workers import app
from page_parse.user import public
from page_get.basic import get_page
from db.wb_data import insert_weibo_datas
from db.seed_ids import get_home_ids
from config.conf import get_max_home_page
from page_parse.home import get_wbdata_fromweb, get_home_wbdata_byajax, get_total_page


# 只抓取原创微博
home_url = 'http://weibo.com/u/{}?is_ori=1&is_tag=0&profile_ftype=1&page={}'
ajax_url = 'http://weibo.com/p/aj/v6/mblog/mbloglist?ajwvr=6&domain={}&pagebar={}&is_ori=1&id={}{}&page={}' \
           '&pre_page={}&__rnd={}'


@app.task(ignore_result=True)
def crawl_ajax_page(url):
    """
    返回值主要供第一次本地调用使用(获取总页数),网络调用忽略返回值
    :param url: 
    :return: 
    """
    ajax_html = get_page(url, user_verify=False)
    ajax_wbdatas = get_home_wbdata_byajax(ajax_html)
    if not ajax_wbdatas:
        return ''

    insert_weibo_datas(ajax_wbdatas)
    return ajax_html


@app.task(ignore_result=True)
def crawl_weibo_datas(uid):
    limit = get_max_home_page()
    cur_page = 1
    while cur_page <= limit:
        url = home_url.format(uid, cur_page)
        html = get_page(url)
        weibo_datas = get_wbdata_fromweb(html)

        if not weibo_datas:
            crawler.warning('用户id为{}的用户主页微博数据未采集成功,请检查原因'.format(uid))
            return

        insert_weibo_datas(weibo_datas)

        domain = public.get_userdomain(html)
        cur_time = int(time.time()*1000)
        ajax_url_0 = ajax_url.format(domain, 0, domain, uid, cur_page, cur_page, cur_time)
        ajax_url_1 = ajax_url.format(domain, 1, domain, uid, cur_page, cur_page, cur_time+100)

        if cur_page == 1:
            total_page = get_total_page(crawl_ajax_page(ajax_url_1))

        if total_page < limit:
            limit = total_page

        cur_page += 1
        app.send_task('tasks.home.crawl_ajax_page', args=(ajax_url_0,), queue='ajax_home_crawler',
                      routing_key='ajax_home_info')

        app.send_task('tasks.home.crawl_ajax_page', args=(ajax_url_1,), queue='ajax_home_crawler',
                      routing_key='ajax_home_info')


@app.task
def excute_home_task():
    # 这里的策略由自己指定,可以基于已有用户做主页抓取,也可以指定一些用户,我这里直接选的种子数据库中的uid
    id_objs = get_home_ids()
    for id_obj in id_objs:
        app.send_task('tasks.home.crawl_weibo_datas', args=(id_obj.uid,), queue='home_crawler',
                      routing_key='home_info')

基本用法:请按照启动worker=>运行login_first.py=> 启动定时任务或者别的任务这个顺序进行

使用任务路由的最大好处是你可以为不同的节点分配不同的任务,这样让整个系统的数据采集效率更高。比如用户抓取,一个http请求只能得到一个用户信息,而对于用户关注和粉丝抓取,一个http请求可以得到几十个关注或者粉丝用户的uid,所以可以部署一个用户关注或者粉丝抓取节点,部署10个或者更多的用户信息抓取节点,让任务能比较均衡地执行。

找一个明星,试试爬取全部内容吧!

原文发布于微信公众号 - Python爬虫与算法进阶(zhangslob)

原文发表时间:2017-07-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java架构

学Java分布式和高架构,必懂的两大知识点!

45640
来自专栏JAVA高级架构

谈谈为什么需要服务治理(Dubbo)

23030
来自专栏云计算D1net

混合云/多云环境如何部署微服务

微服务能够为混合云或多云部署带来大量的好处,但是它们也能够带来与网络、安全性等相关的新挑战。 ? 大多数IT企业已经开始认识到在开发和部署中实施软件组件化的好处...

35990
来自专栏九彩拼盘的叨叨叨

前端共同成长小组手册

13810
来自专栏葡萄城控件技术团队

应用系统中交互式报表功能解析

从报表需求的整个发展历程来看,可以分为两个阶段: 1、静态报表:解决显示、打印、导出报表数据的需要。 2、交互式报表:解决终端用户分析数据的需要,通常会用到数据...

191100
来自专栏圣杰的专栏

DDD理论学习系列(8)-- 应用服务&领域服务

1. 引言 单从字面理解,不管是领域服务还是应用服务,都是服务。而什么是服务?从SOA到微服务,它们所描述的服务都是一个宽泛的概念,我们可以理解为服务是行为的抽...

329100
来自专栏前端架构与工程

浅析前端工程化

1. 什么是前端工程化 自有前端工程师这个称谓以来,前端的发展可谓是日新月异。相比较已经非常成熟的其他领域,前端虽是后起之秀,但其野蛮生长是其他领域不能比的。虽...

50670
来自专栏BestSDK

可视化数据埋点,可以把PM提升一个“质”的高度

在这一个大数据的时代,在这一个产品经理爱拍脑袋的时代,数据的重要性不言而喻,好的数据分析可以使我们的产品不偏离正确的轨道,做好数据分析的第一步就是做好数据埋点,...

43740
来自专栏ytkah

公众号和小程序可以同名了 名称支持同主体复用

  公众号和小程序不能同名?现在可以了!以前,小程序的名称不能和现有的公众号同名,现在支持同主体的情况下,小程序和公众号可以同名了。公众号、小程序在名称唯一的前...

72930
来自专栏全华班

Android平台开发学习实践

今天整理下关于android的学习思维和方法 Android的思维 做一个开源框架,送给全世界来“玩耍”。 Google我来做一条强龙,开发人员做一条小地头...

38780

扫码关注云+社区

领取腾讯云代金券