新浪微博爬虫阶段总结

首先,这是项目地址。
做这个爬虫的过程中,遇到了无数的坑,但是还好都填补上了,但是还是有几个问题实在是难以解决。暂时先记录如下。

  • MySQL的bug?python执行时传入了正确的语句,但是却出现了插入了错误的数据
  • 分属不同文件的消费者生产者不把队列赋值给类的属性,并作为参数传入子进程无法进行通信
  • cannot serialize _io.BufferedReader object问题总结反思

其中第一个问题应该是MySQL的设计问题,但是目前也没有找到原因,但是利用ignore倒是成功解决插入的主键冲突问题。
后两个问题很是奇葩,都是仅产生一次两次的问题,现在完全就不会有这个问题出现。所以我也不是很懂了,但是还是记录下来,这里面可能有什么地方存在着问题。

整体思路

对于这个爬虫项目,我是希望能够进行大规模的爬取,能够获取到较为大量的数据,所以一开始便需要对起进行一定的规划。因此,我将该爬虫划分为以下几个部分

  • Downloader 该部件主要用于下载数据,将数据传送到Spider中用于解析
  • Spider 该部件用于解析数据,然后将其放入数据库中‘
  • Database 显而易见,这是用于处理数据库的部件
  • Schedule 该部件用于从数据库中获取需要爬取的用户信息,然后构造网址进行爬取
  • transmission 这里包含了RequestResponse,这两个类封装了请求信息和获取到的信息,方便Spider进行归类整理
  • middlequeue 这一块用于存在数据传输的队列,方便不同的部件进行通信,直接利用了multiprocessingQueue
  • ErrorDeal 本来这个是用来处理请求失败的链接的,但是后来发现并不需要了,所以直接就扔了
  • ProxyCreate 该部件用于整理获取代理,但是因为各家的代理实在是太废了,然后发现了一家动态转发的代理服务商的服务不错,所以直接采用他家的服务,不再自己去获取代理。

这个爬虫的代码下载数据部分我采用的是多进程加协程进行请求,其他的部分直接利用单进程不断的循环便足够处理了。

分类

总结

新浪微博的数据在手机端可以免登录的获取,所以转战手机端。对于每个用户要获取其具体的粉丝关注者微博详情,需要知道各项的具体数量才能够进行页码构造。因此整个过程会比较绕。简要记为以下几点

  • 对于用户信息需要请求两个不同的网址才能够得到其完整信息,不过第二次所得到的信息并不十分重要,但还是一并获取了
  • 请求粉丝数据,关注者数据时,可以得到一定的用户信息,但是该信息会给假数据,所以只能从中获取到用户ID
  • 微博详情的数据中也可以获取到一定的用户信息,但是目前感觉这个部分的用户信息没啥意义,所以直接抛弃了
  • 利用触发器,将存入粉丝和关注者数据库中的ID都转存一份到用户详情数据库中
  • 对于用户详情数据库,利用一个冗余量来标记其目前的状态(具体在代码注释中有写),给Schedule提供调取信息
  • SpiderDownloader 中专门开一个进程用于用户信息的获取,防止用户信息的请求被堆积在各类请求中,导致后续无法进行网址构造
  • 种子用户即为我自己的微博账号

Downloader

Downloader这一部分,采用多进程加协程对请求进行处理,之前的测试速度是每秒钟MySQL增加12条记录,整体速度相应的还是比较慢,可能是开了太多进程的原因。代理采用的服务商的动态转发服务。
我将Downloader划分为两个部分

  • 用户详细信息下载进程 该进程仅用于下载用户的详细信息。当出现下载错误时,该Request再次进入下载队列,等待下一个下载
  • 粉丝关注者微博详情下载进程 该进程用于下载其他的信息,用info来统一标识,对于该进程的下载错误问题,将会进入一个错误队列,该错误队列直接进入Schedule,由Schedule安排下次下载

对于Downloader的错误错误问题,额外记录一个失败次数,一旦返回的数据长度小于500,且失败了一定次数后,便丢弃该Request。这里的失败次数暂时定为3次。有了这个规则在,对于info的具体页码制定规则便可以不用过多考虑。

Schedule

构造网址的工作交由Schedule处理。Schedule从数据库中获取用户详情和用户ID。将网址封装在Request中,传入请求队列。Schedule的工作分为以下三个部分

  • 用户信息请求单独放入一个Queue中
  • 用户详情信息请求放入另一个Queue中。为防止在某一固定时间段内总是在获取同一用户的某一信息。所以对于用户的粉丝关注者微博详情三种类别的请求,将随机取一小段放入队列中,直到所有信息请求网址都完全放入队列中
  • Schedule会接收从Downloader传过来的错误请求网址,每次将取一定的个数放入详情请求队列中

Spider

该部件用于解析新浪的json数据,并将其存入数据库中。该部件直接采用单进程的模式即可。
需要注意的事,对于微博详情的时间。只有刚发的微博的时间会显示出具体到分,而之前的时间都是到天。所以微博详情的时间一律以天为最小单位。

Database

数据库采用MySQL。需要注意的是,因为微博处于不断的动态变化,所以插入的数据可能会跟数据库中已有的数据产生冲突。我一开始采用的是ON DUPLICATE KEY UPDATE语句来防止冲突,后来发现该语句会导致数据库产生奇怪的数据问题,见上文链接,后来在别人的博客中发现了IGNORE这个关键词,可以有效的防止主键冲突问题。
后期需要的话,可能需要将数据库进行分表处理。目前主要的想法如下

  • 微博详情根据推文长度进行分表
  • 用户ID对应到一个序号,在各个表中仅存储ID序号

对于输入到粉丝数据表,关注者信息数据表的数据,将会有一个触发器将粉丝和关注者ID复制一份到用户信息数据库中,用于后续的抓取。

Log模块

为了方便记录各类信息,后面特意加上了日志记录。
但是出现了很奇怪的事。在DownloaderSpider模块里,如果在子进程里创建log对象,那么记录下载的日志信息将会出现重复的两条,对于这个问题也是很无解了。能发现这个原因是因为我发现Schedule的日志信息都不会有重复的出现,可是DownloaderSpider都会出现,于是觉得可能问题是出在了子进程的日志对象里。
于是便在类初始化时创建日志对象,之后直接调用,然后问题就得以解决。但是该问题的原因目前也不是很清楚。

后期规划

现在手上有两台服务器,所以打算将其做成一个分布式的爬虫。难点主要出现在,我觉得两台服务器都有50G的硬盘空间,如果不用来存东西感觉很是浪费。
为了保证不重复的抓取,我目前打算腾讯云的服务器用来做主机,阿里云的服务器用来做从机。阿里云的服务器存用户详情数据,对于从粉丝和关注者中得到的用户ID,通通发回给腾讯云的机子。腾讯云的机器一方面进行用户详情的获取,一方面也做用户粉丝关注者微博详情的获取。

整个分布式系统分为三个部分。

  • 分发系统。该系统用于发放需要抓取的用户详细信息
  • 用户信息完善系统。该系统分布于一台主机,用于完善用户信息
  • 各项信息抓取系统,该系统可以分布在多台机器上

你可能感兴趣的:(python,python,微博爬虫,爬虫,新浪微博数据)