赞
踩
bilibili用户已经突破7亿了(根据UID来看)
Github: Leopard-C/BiliUserSpider
bilibili御坂网络计划:https://misaka.sisters.top
只保留与此相关的数据,其余数据已删除
开发环境
| 服务器 | 客户端 | 管理程序 | |
|---|---|---|---|
| 语言 | C++11 | C++11 | C++11 |
| 开发环境 | Linux/vim/xmake | VS2017 | VS2017+Qt5.12 |
| 运行环境 | Linux | Windows / Linux | Windows |
其他环境
| 配置项 | 值 |
|---|---|
| 数据库 | MySQL-8.0.20 |
客户端是在Windows下开发的,但是代码可以直接放到到Linux上编译运行。
管理程序是在Windows下用VS2017开发的,也可以移植到Linux上使用Qt Creator开发(没有测试,不过代码基本上没有用到平台相关的函数,有的话也通过
_WIN32宏进行了区分)。服务器和客户端均可在内网或公网上运行,只要能够通过IP或域名访问到即可。


使用的代理IP提供商,IP有效时间1-5分钟,不固定,所以通过记录每个代理IP请求失败的次数,达到阈值(比如30)就认为该IP失效,清除该IP。
管理客户端,包括客户端的加入、退出、心跳检测。
管理爬虫任务,包括申请任务、提交任务。任务结构体定义如下:
struct BiliTask {
int clientId; /* 申请该任务的客户端ID */
unsigned int midStart; /* 起始用户ID */
unsigned int midEnd; /* 终止用户ID(不含) */
time_t ttl; /* 过期时间,如果在这之前没有提交任务,就回收该任务,重新分配 */
};
更新代理IP数据库。根据购买的代理IP的使用规则,间隔指定时间,从服务商那里获取新的代理IP,添加到数据库,同时,清除数据库中失效的代理IP(失败次数达到阈值)。
这里客户端,指的是一个进程。每个进程中又运行着多个线程,真正的爬虫过程是在线程里执行的。
每个客户端:
维护一个代理IP池,或者称之为代理IP管理器。(src/manager/ProxyManager),关键成员变量是proxies
// <代理IP信息,失败次数>
std::map<ProxyData, int> proxies;
维护一个任务分配管理器(为了和服务器端区分,这里称之为LocalTaskManager)。
LocalTaskManager向爬虫服务器的任务管理器(这里称之为ServerTaskManager)申请一个MainTask,然后细分为许多个SubTask,下发给每个爬虫线程。如果MainTask下发完毕(可能还没有完成),就继续申请MainTask。
爬虫线程向LocalTaskManager提交SubTask:
LocalTaskManager申请任务时,优先分配这些用户ID。MainTask全部执行完成,提交到ServerTaskManager。(凡是提交的任务,任务中的所有用户信息都爬取成功并写入了数据库!!!)
/* 主任务 */ struct MainTask { MainTask() = default; MainTask(int id, unsigned int start, unsigned int end) : id(id), midStart(start), midEnd(end) {} bool isCompleted() const { return completed >= midEnd - midStart; } int id = -1; unsigned int midStart = 0; unsigned int midEnd = 0; unsigned int completed = 0; }; /* 子任务 */ struct SubTask { SubTask(int mainTaskId, const std::vector<unsigned int>& mids) : mainTaskId(mainTaskId), mids(mids) {} int mainTaskId; /* 该子任务所属的主任务的id */ std::vector<unsigned int> mids; };
三种数据表



以下每个进程中都开了50个线程。
【注意】 客户端必须能够通过IP访问到服务器和Mysql数据库,服务器也必须能够访问到Mysql数据库。
客户端只需要配置一个配置文件 config/spider.json,填入爬虫服务器的地址、启动的爬虫线程数 和Token。然后运行即可。
{
"server_addr": "10.133.xxx.xxx:10033",
"threads": 50,
"token": "bhKyhZpFAp3T"
}
至于其他配置(比如MySQL数据库信息,爬虫超时设置等),都是直接从服务器端获取,所以只需要知道爬虫服务器的地址就行了。
如4.4所示(最终版)
最快的时候可以850 ~ 1100 个用户/秒,每天累计 8千万+,理论上可以更快,但是需要人留意观察,白天一般满速爬取,晚上睡觉前一般关掉几个客户端,降低一下爬虫速度,防止出现”击穿的情况“(此问题已解决)。
爬虫速度由两方面决定
这个速度基本上达到了代理IP的瓶颈(利用率估计90%+),计算机的性能倒是没有达到瓶颈(CPU利用率低于30%,爬虫的同时,不影响正常使用)
我认为提高代理IP使用率的方法,是将爬虫的超时时间设置大一点,允许的错误次数设置多一点,然后就是疯狂开进程(+线程),比如开几十个上百个进程,上千个线程。这样可以榨干代理IP。(只是个人见解)


人生苦短,我用C++。
C++可以写爬虫。
C++写爬虫可能不是一个好的选择。
C++写的爬虫可以很强大。
Github: Leopard-C/BiliUserSpider
Email: leopard.c@outlook.com
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。