2020年最新微博相關數據API+一站式獲取個人微博信息+套娃、批量式獲取微博用戶信息

本此爬蟲採取scrapy框架進行編寫。

1. 梳理爬蟲目的和思路

1.1 爬蟲的目的

  • 爬取博主的個人信息,包括名字,微博認證內容,粉絲數,關注數等
  • 爬取博主的關注列表,包括列表裏的每個人的個人信息
  • 爬取博主的粉絲列表,包括列表裏的那個人的個人信息
  • 爬取博主的微博內容,包括髮微博的時間,來源,圖片的鏈接,內容等

1.2 爬蟲的思路

  • 分析網頁源碼,尋找其分裝json數據響應的Request URL的規律,得到其微博相關數據API
  • 請求API,捕獲返回的json數據
  • 分析這些json數據,提取自己有用的數據
  • 將數據保存入數據庫

2. 分析網頁源碼

爬取的微博網址是手機端微博的登陸網址

2.1 分析博主信息網頁

該網頁是手機端微博登陸自己的微博後,打開自己的主頁,f12打開面板,直接查看XHR下的請求,因爲之前爬取過微博的爬蟲,採用的不是框架爬蟲,
Python幫你瞭解你喜歡的人!爬取她的微博內容信息!(Ajax數據爬取)
發現微博的數據是通過Ajax的方式加載的,故直接查看XHR下的響應,因爲是指爬取博主的個人信息,所以不用下拉頁面,直接f5刷新以下在出現的響應中進行爬取。很簡單就可以找見如圖所示的響應,發現個人信息就在data->user下,整體的數據返回格式是json,其RequestURL可以發現其就是最後的uid在發生變化
在這裏插入圖片描述
在這裏插入圖片描述

2.2 分析關注列表界面

點擊其關注就可以進入其關注列表頁面:
下拉頁面,就會看見出現的請求響應,很明顯這就是其加載關注列表的響應,分析其RequestURL鏈接,發現其請求變化的規律也是在於uid的變化和page的變化,其關注列表的信息在data->card_group中,列表中的每個人的信息在user中,其返回的數據格式也是json
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

2.3 粉絲列表頁面分析

點擊其粉絲便可進入其粉絲頁面:
下拉粉絲也面,在XHR下也會看見加載的響應,便是存儲粉絲列表的響應,其RequestURL鏈接的變化之初也是uid和since_id在變,一個標識用戶,一個改變頁數。其數據在data->cards下保存,每個粉絲的用戶信息在usr中保存,數據的返回格式也是JSON。
在這裏插入圖片描述
在這裏插入圖片描述

2.4 微博博文頁面分析

在其主頁面,點擊最下方的查看全部微博,便可以進入其微博博文頁面:
下拉頁面,在XHR下便可以看見加載的請求響應,其RequestURL的變化也是在於uid和page的變化,微博數據在data->cards->mblog中保存,整體的數據返回格式是JSON。
在這裏插入圖片描述
在這裏插入圖片描述

3. 得出2020年最新微博相關數據API

綜上所述,得出相關的微博相關數據的API:

    # 用戶詳情API
    user_url = 'https://m.weibo.cn/profile/info?uid={uid}'
    # 關注列表API
    follow_url = 'https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_{uid}&page={page}'
    # 粉絲列表API
    fan_url = 'https://m.weibo.cn/api/container/getIndex?containerid=231051_-_fans_-_{uid}&since_id={page}'
    # 微博內容API
    weibo_url = 'https://m.weibo.cn/api/container/getIndex?containerid=230413{uid}_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&page={page}'

4. 編寫代碼

4.1 創建Scrapy爬蟲項目

scrapy startproject weiboinfo

4.2 創建Spider

在Pycharm下端的Terminal中執行即可:

scrapy genspider weibo m.weibo.cn

4.3 根據網頁源碼下user下的信息,創建自己想提取的信息所對應的Item

在items.py下定義:

class UserItem(Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    id = Field()
    # 博主名字
    screen_name = Field()
    # 個人簡介
    description = Field()
    # 關注數
    follow_count = Field()
    # 粉絲數
    followers_count = Field()
    # 是否關注自己
    follow_me = Field()
    # 自己是否關注他
    following = Field()
    # 微博認證
    verified_reason = Field()
    # 微博鏈接
    profile_url = Field()
    # 全部微博數
    statuses_count = Field()

class UserAttentionItem(Item):
    id = Field()
    # 博主名字
    screen_name = Field()
    # 關注數
    follow_count = Field()
    # 粉絲數
    followers_count = Field()
    # 是否關注自己
    follow_me = Field()
    # 自己是否關注他
    following = Field()
    # 微博鏈接
    profile_url = Field()

class UserFansItem(Item):
    id = Field()
    # 博主名字
    screen_name = Field()
    # 關注數
    follow_count = Field()
    # 粉絲數
    followers_count = Field()
    # 微博鏈接
    profile_url = Field()
    # 微博簡介
    desc1 = Field()
    desc2 = Field()

class WeiboItem(Item):
    id = Field()
    # 點贊數
    attitudes_count = Field()
    # 評論數
    comments_count = Field()
    # pictuer 鏈接
    picture_url = Field()
    # 內容
    raw_text = Field()
    # 來源
    source = Field()
    # 發佈時間
    created_at = Field()

4.4 進行數據的提取

4.4.1 創建程序的起始請求

class WeiboSpider(scrapy.Spider):
    name = 'weibo'
    allowed_domains = ['m.weibo.cn']
    #start_urls = ['http://m.weibo.cn/']
	
	# 這裏寫的是你想要爬取博主信息的uid
    start_users = ['uid']

    # 用戶詳情API
    user_url = 'https://m.weibo.cn/profile/info?uid={uid}'
    # 關注列表API
    follow_url = 'https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_{uid}&page={page}'
    # 粉絲列表API
    fan_url = 'https://m.weibo.cn/api/container/getIndex?containerid=231051_-_fans_-_{uid}&since_id={page}'
    # 微博內容API
    weibo_url = 'https://m.weibo.cn/api/container/getIndex?containerid=230413{uid}_-_WEIBO_SECOND_PROFILE_WEIBO&page_type=03&page={page}'

    def start_requests(self):
        for uid in self.start_users:
            yield Request(self.user_url.format(uid=uid),callback=self.parse_user)

4.4.2 提取博主個人信息

   '''
    爬取博主個人信息
    '''
    def parse_user(self, response):
        result = json.loads(response.text)
        if result.get('data').get('user'):
            user_info = result.get('data').get('user')
            user_item = UserItem()
            user_item['id'] = user_info.get('id')
            user_item['screen_name'] = user_info.get('screen_name')
            user_item['description'] = user_info.get('description')
            user_item['follow_count'] = user_info.get('follow_count')
            user_item['followers_count'] = user_info.get('followers_count')
            user_item['follow_me'] = user_info.get('follow_me')
            user_item['following'] = user_info.get('following')
            user_item['verified_reason'] = user_info.get('verified_reason')
            user_item['profile_url'] = user_info.get('profile_url')
            user_item['statuses_count'] = user_info.get('statuses_count')
            yield user_item
            #獲取博主的id,進行構造下一項的請求
            id = user_info.get('id')
            # 關注
            yield Request(self.follow_url.format(uid=id,page=1),callback=self.parse_follows,meta={'page':1,'uid':id})
            # 粉絲
            yield Request(self.fan_url.format(uid=id,page=1),callback=self.parse_fans,meta={'page':1,'uid':id})
            # 微博
            yield Request(self.weibo_url.format(uid=id,page=1),callback=self.parse_weibos,meta={'page':1,'uid':id})

4.4.3 提取博主關注列表及其用戶信息

    '''
    爬取博主關注列表信息
    '''
    def parse_follows(self,response):
        result = json.loads(response.text)
        if result.get('ok') and result.get('data').get('cards') and len(result.get('data').get('cards')) and result.get('data').get('cards')[-1].get('card_group'):
            follows = result.get('data').get('cards')[-1].get('card_group')
            for follow in follows:
                if follow.get('user'):
                    uid = follow.get('user').get('id')
                    #yield Request(self.user_url.format(uid=uid),callback=self.parse_user)
                user_AttentionItem = UserAttentionItem()
                user_AttentionItem['id'] = follow.get('user').get('id')
                user_AttentionItem['screen_name'] = follow.get('user').get('screen_name')
                user_AttentionItem['follow_count'] = follow.get('user').get('follow_count')
                user_AttentionItem['followers_count'] = follow.get('user').get('followers_count')
                user_AttentionItem['follow_me'] = follow.get('user').get('follow_me')
                user_AttentionItem['following'] = follow.get('user').get('following')
                user_AttentionItem['profile_url'] = follow.get('user').get('profile_url')
                yield user_AttentionItem

                # 關注列表翻頁
                uid = response.meta.get('uid')
                page = response.meta.get('page') + 1
                yield Request(self.follow_url.format(uid=uid,page=page),callback=self.parse_follows,meta={'page':page,'uid':uid})

4.4.4 提取博主粉絲列表及其用戶信息

    '''
    爬取博主粉絲列表信息
    '''
    def parse_fans(self,response):
        result = json.loads(response.text)
        if result.get('ok') and result.get('data').get('cards') and len(result.get('data').get('cards')) and result.get('data').get('cards')[-1].get('card_group'):
            fans = result.get('data').get('cards')[-1].get('card_group')
            for fan in fans:
                if fan.get('user'):
                    uid = fan.get('user').get('id')
                    #yield Request(self.user_url.format(uid=uid),callback=self.parse_user)
                # 分析列表
                user_FansItem = UserFansItem()
                user_FansItem['id'] = fan.get('user').get('id')
                user_FansItem['screen_name'] = fan.get('user').get('screen_name')
                user_FansItem['follow_count'] = fan.get('user').get('follow_count')
                user_FansItem['followers_count'] = fan.get('user').get('followers_count')
                user_FansItem['desc1'] = fan.get('desc1')
                user_FansItem['desc2'] = fan.get('desc2')
                user_FansItem['profile_url'] = fan.get('user').get('profile_url')
                yield  user_FansItem

                # 分析列表 翻頁
                uid = response.meta.get('uid')
                page = response.meta.get('page') + 1
                yield Request(self.fan_url.format(uid=uid,page=page),callback=self.parse_fans,meta={'page':page,'uid':uid})

4.4.5 提取博主微博內容

    '''
    爬取微博內容
    '''
    def parse_weibos(self,response):
        result = json.loads(response.text)
        if result.get('ok') and result.get('data').get('cards'):
            weibos = result.get('data').get('cards')
            for weibo in weibos[1::]:
                mblog = weibo.get('mblog')
                if mblog:
                    weibo_item = WeiboItem()
                    weibo_item['id'] = mblog.get('id')
                    weibo_item['attitudes_count'] = mblog.get('attitudes_count')
                    weibo_item['comments_count'] = mblog.get('comments_count')
                    weibo_item['picture_url'] = mblog.get('bmiddle_pic')
                    weibo_item['raw_text'] = mblog.get('raw_text')
                    weibo_item['source'] = mblog.get('source')
                    weibo_item['created_at'] = mblog.get('created_at')
                    yield weibo_item

                # 微博內容翻頁
                uid = response.meta.get('uid')
                page = response.meta.get('page') + 1
                yield Request(self.weibo_url.format(uid=uid,page=page),callback=self.parse_weibos,meta={'page':page,'uid':uid})

5. 建立相應的數據庫

數據庫中表的信息所建立的字段跟item中創建的Field一一對應即可。

5.1 數據庫如圖所示:

在這裏插入圖片描述

6. 連接數據庫並將數據存入數據庫

在 pipelines.py 中寫入如下代碼:

class PymysqlPipeline(object):
    #連接數據庫
    def __init__(self):
        self.connect = pymysql.connect(
            host = 'localhost',
            database = 'weibo',
            user = 'root',
            password = '123456',
            charset = 'utf8',
            port = 3306
        )
        # 創建遊標對象
        self.cursor = self.connect.cursor()

    # 此方法是必須要實現的方法,被定義的 Item Pipeline 會默認調用這個方法對 Item 進行處理
    def process_item(self,item,spider):
        # 判斷item是哪一類的item
        if isinstance(item,UserItem):
            cursor = self.cursor
            sql = 'insert into userItem(id,screen_name,description,follow_count,followers_count,follow_me,following,verified_reason,statuses_count,url) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
            cursor.execute(sql,(
                item['id'],item['screen_name'],item['description'],item['follow_count'],item['followers_count'],item['follow_me'],item['following'],item['verified_reason'],item['statuses_count'],item['profile_url']
            ))
            # 提交數據庫事務
            self.connect.commit()
            return item
        if isinstance(item,UserAttentionItem):
            cursor = self.cursor
            sql = 'insert into userAttentionItem(uid,screen_name,follow_count,followers_count,follow_me,following,profile_url) values (%s,%s,%s,%s,%s,%s,%s)'
            cursor.execute(sql,(
                item['id'],item['screen_name'],item['follow_count'],item['followers_count'],item['follow_me'],item['following'],item['profile_url']
            ))
            #提交數據庫事務
            self.connect.commit()
            return item
        if isinstance(item,UserFansItem):
            cursor = self.cursor
            sql = 'insert into userfansitem(id,screen_name,follow_count,followers_count,desc1,desc2,profile_url) values (%s,%s,%s,%s,%s,%s,%s)'
            cursor.execute(sql,(
                item['id'],item['screen_name'],item['follow_count'],item['followers_count'],item['desc1'],item['desc2'],item['profile_url']
            ))
            self.connect.commit()
            return item
        if isinstance(item,WeiboItem):
            cursor = self.cursor
            sql = 'insert into weiboitem(id,attitudes_count,comments_count,picture_url,raw_text,source,created_at) values (%s,%s,%s,%s,%s,%s,%s)'
            cursor.execute(sql,(
                item['id'],item['attitudes_count'],item['comments_count'],item['picture_url'],item['raw_text'],item['source'],item['created_at']
            ))
            self.connect.commit()
            return item

6.1 啓動pipline

#開啓自己寫的 Pipeline
ITEM_PIPELINES = {
    'weiboinfo.pipelines.PymysqlPipeline':300
}

7. 套娃、批量式獲取微博用戶信息

這個功能在上述的代碼編寫的時候就已經實現了,由於是不斷的迭代爬取,後臺在一直出現數據,按理來說是很難自動停下來的,所以我將構建迭代請求的代碼註釋掉,次全部代碼的功能爲分析一個人的微博用戶,可以爬取其個人信息,關注列表,粉絲列表,所發的微博內容信息。

不想迭代式爬取的第二個原因是,存儲困難,mysql數據庫無法按自己的想法存儲對應的信息,比如,我想對兩位博主的信息進行爬取,將兩位博主各自的關注列表,粉絲列表各存儲到一個表當中,但是因爲公用的是一個item,無法實現分別存放,只能生硬的存放到一個表當中,存儲的方式感覺不是很得當,或者是自己沒有想到更好的解決方法…

若想實現套娃、迭代式的爬取,只需將如下圖的代碼接觸註釋即可:
在這裏插入圖片描述
在這裏插入圖片描述

8. 代碼存在的問題

此代碼,在反爬方面僅在setting.py當中添加了不同的headers,和構造了基礎的請求頭信息,自己在迭代爬取的過程當中發現,當爬取的數據一次性超過1100條以上,自己的ip地址將會被短暫的禁止訪問網頁,所以這裏的反爬做的很是不好,自己還得努力,爭取學會搭建cookies池…

9. 爬取的結果

9.1 後臺結果

在這裏插入圖片描述

9.2 數據庫結果

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
代碼中有出現的錯誤和什麼論述不對的地方,請評論或私信指出我立馬改正。

大家有什麼好的建議也可以評論或私信指出,小白接受任何批評😁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章