攻克微博(2) - 抓取关注和个人信息

思路

uid

首先要明确一点,新浪每个用户都有一个uid。举个例子,北美吐槽君的uid是3177527181

攻克微博(2) - 抓取关注和个人信息_第1张图片
weibo-homepage.jpg

通过请求https://weibo.com/uid/profile就可以访问到如上页面,途中红框所在的位置就是我们第一步要抓的索引页,分别是关注页面、粉丝页面、微博页面和相册,另外还有个人信息页面,URL是https://weibo.com/uid/info

这样通过任意一个uid,我就可以获得其对应的所有页面的URL,之后就可以按需抓取。

一般来说,关注或者粉丝页面有一个是必须要抓取的,因为如果要让爬虫不断抓取,你需要不断扩充你的爬取对象列表,这里我的对象列表是一个包含uid的列表,一开始的时候只有一个uid,也就是start_url。之后每次抓取一个uid,都会抓取器关注列表,然后将关注列表里的uid添加到对象列表中。

我这里抓取了两个页面:关注页面和个人信息页面。

关注页面

攻克微博(2) - 抓取关注和个人信息_第2张图片
weibo-follow.jpg

之后我们会抓取表格中每一项的usercard标签,这里要注意的是,像图中的留学帮帮问其实是一个公共主页或者热门话题,是不存在usercard标签的,需要剔除。其他诸如抓取下一页地址之类的问题就不多说了。需要注意的是,根据新浪的规定,如果你所在的账户和你抓取的对象不是互相关注的,你只能查看其前五页的关注列表。这限制了之后人际关系网的分析,不过暂时对于我们扩展对象列表来说已经足够了。

个人信息页面

攻克微博(2) - 抓取关注和个人信息_第3张图片
weibo-info.jpg

这个直接抓就行了。

当前用户页面和抓取页面

这里要提一点就是,如果你查看自己的关注页面和查看别人的关注页面,两个页面是不一样的。因为你可以管理自己的关注列表,这意味着自己的关注页面其实是一个可以与服务器交互的表单。个人信息页面会存在相同的问题。因此,我们要做的是将你自己的uid从对象列表中去除。

去重问题

我这里使用的是BloomFilter去重,后端使用sqlite3,同时给表中的uid字段加入唯一索引。这是因为BloomFilter是有错误率的,但是即使它出错了,后端也可以保证不会重复插入数据。同时因为BloomFilter的存在,也避免了后端一直出现重复插入的问题。

BloomFilter在程序启动的时候初始化,它会根据当前数据库中所有的uid进行初始化,之后每次抓到uid后都会先去BloomFilter校验一下,看是不是已经抓取过了。

代码

weibo.py

import requests
import time
from bs4 import BeautifulSoup
from random import choice
import os
import re
from pybloom import ScalableBloomFilter

import Configure
import getCookie
import Sqlite3api as sqlite3

conn = None

bf_uid = ScalableBloomFilter(initial_capacity=1000, error_rate=0.001, mode=ScalableBloomFilter.SMALL_SET_GROWTH)
start_uid = [1845178932]
uid_list = start_uid

header = {}
header['user-agent'] =  choice(Configure.FakeUserAgents)

cookies = {}

domain = 'https://weibo.com'

# 这个方法返回一个字典,根据uid访问并抓取
# 关注,粉丝,微博,个人信息和相册的地址
# 其中个人信息不是抓出来,而是直接用uid构造的
# 为了结构清晰,一并并入
def get_index_by_uid(uid):
    print ("Start to crawl user[{0:d}] profile.".format(uid))

    ret = {}

    url = "https://weibo.com/{0:d}/profile".format(uid)

    try:
        response = requests.get(url, headers=header, cookies=cookies)
        content = None

        if response.status_code == requests.codes.ok:
            content = response.text
            
    except Exception as e:
        print (e)

    # 看是不是公共主页,或者超级话题
    pattern = re.compile('
                    
                    

你可能感兴趣的:(攻克微博(2) - 抓取关注和个人信息)