社交網絡 分析與實現

前言

最近國產的一部電視劇《人民的名義》突然的就火了,隨之而來的是各大Coder們的社交網絡分析。針對劇本中出現的人名,事件,詞頻等以圖形化的界面展示,清晰化的顯示出了劇本的特色。

而對于CSDN的關注人和粉絲的圖形化展示,也恰好符合這一個主題(暫且這么認為吧)。本來想做的是公共粉絲(比如哪個人既關注了A,又關注了B),但是在博客中由于權限的問題,獲取不到相關的數據,于是只能做下關注人和粉絲的圖形化展示了。

先來看下最終效果圖。


“社交網絡分析效果圖”

環境

從上面的效果圖上也可以看出,命令行前面有一個(env)的前綴,這是使用了virtualenv的緣故。

virtualenv

使用virtualenv可以很好的隔絕本地的Python環境,而且也不是很占用磁盤空間,對每一個項目使用一個單獨的環境還能大大減少出現意外的頻率,更好的維護代碼,排查錯誤。

安裝virtualenv也非常的簡單。

pip install virtualenv

安裝好之后,就可以在任意的目錄下,使用命令行執行下面的命令。比如我在桌面新建了一個名為nerwork的文件夾,我就可以進入到這個文件夾內部,打開命令行,執行:

virtualenv env

這樣network文件夾下就會多出一個env的目錄,里面的環境就是根據我們本地的Python環境而新建的一個隔離區。

這樣還不算完成,最后一步就是激活這個虛擬環境。執行:

env\Scripts\activate.bat

如果前綴變成了(env)XXX,那就說明虛擬環境激活成功了,我們只需要在這個虛擬環境中進行開發就可以了。

第三方庫

這里需要用到一些第三方的庫,通過pip freeze命令,可以詳細的查看每一個庫的名稱以及精確的版本號。

(env) C:\Users\biao\Desktop\network\code\relationanalysis>pip freeze
appdirs==1.4.3
beautifulsoup4==4.6.0
csdnbackup==0.0.1
cycler==0.10.0
decorator==4.0.11
matplotlib==2.0.2
networkx==1.11
numpy==1.12.1
packaging==16.8
pyparsing==2.2.0
python-dateutil==2.6.0
pytz==2017.2
requests==2.14.2
six==1.10.0

但是我們需要安裝的卻不多,因為很多庫是與之關聯的,pip命令會自動把依賴的包幫我們安裝。我們需要安裝的包如下:

  • networkx: pip install networkx
  • csdnbackuo: 這個包是我之前寫過的一個關于CSDN博客備份的工具庫,源碼上傳到了GitHub。而且為了方便使用,我把它做成了一個.whl包,下面是下載地址:
    https://github.com/guoruibiao/csdn-blog-backup-tool
    下載里面適合自己Python版本的whl文件,然后執行
    pip install csdnbackup-0.0.1-py2.py3-none-any.whl 即可。

這樣,依賴的庫就基本上安裝成功了。

模塊化

完成一個任務,首先并不是上來就寫代碼。而是先搞清楚需求。比如這里,要做的是關注人和粉絲的圖形化展示。那么仔細想想,不難發現可以細化這個大任務。

  • 獲取粉絲信息
  • 獲取關注人信息
  • 關于圖形化展示的部分

這樣一來,我們只需要每次完成一個小任務,最終通過集成測試就能完成任務了。下面針對每一個小任務進行實現。

爬蟲模塊

這里的爬蟲模塊不是必須要用我那個庫,你也可以自己寫。但是重復造輪子是一件很枯燥的事,人生苦短,咱還是用輪子吧

關于模擬登陸

from csdnbackup.login import Login

然后使用下面的代碼即可實現模擬登陸。

# coding: utf8

# @Author: 郭 璞
# @File: logintest.py                                                                 
# @Time: 2017/5/18                                   
# @Contact: 1064319632@qq.com
# @blog: http://blog.csdn.net/marksinoberg
# @Description: csdnbackup模擬登陸測試
from csdnbackup.login import Login
import getpass
#
username = input('請輸入您的賬號:')
password = getpass.getpass(prompt='請輸入您的密碼:')

loginer = Login(username=username, password=password)
session = loginer.login()
headers = loginer.headers
headers['Host'] = 'blog.csdn.net'
response = session.get('http://blog.csdn.net/marksinoberg', headers=headers)
print(response.status_code)
print(response.text)
print("網頁總長度:", len(response.text))


沒有圖不足以證實此輪子的好用。

模擬登陸結果驗證

爬取數據

巧婦難為無米之炊,下面來弄點出來。

# coding: utf8

# @Author: 郭 璞
# @File: spider.py                                                                 
# @Time: 2017/5/18                                   
# @Contact: 1064319632@qq.com
# @blog: http://blog.csdn.net/marksinoberg
# @Description: 爬蟲,爬取博主的粉絲信息

from csdnbackup.login import Login
from bs4 import BeautifulSoup
import math
import numpy as np

class Fans(object):

    def __init__(self, domain, password):
        self.domain = domain
        self.loginer = Login(username=domain, password=password)
        self.session = self.loginer.login()
        # set the headers
        self.headers = self.loginer.headers
        self.headers['Referer'] = 'http://blog.csdn.net/{}'.format(self.domain)
        self.headers['Host'] = 'my.csdn.net'

    def get_fans_number(self):
        url = 'http://my.csdn.net/{}'.format(self.domain)

        response = self.session.get(url=url, headers=self.headers)
        # print(response.text)
        if response.status_code == 200:
            soup = BeautifulSoup(response.text, 'html.parser')
            return soup.find('a', {'href': '/my/fans'}).get_text()
        else:
            return 0

    def get_fans(self):

        fans = []

        url = 'http://my.csdn.net/{}'.format(self.domain)
        fans_number = self.get_fans_number()
        pages = math.ceil(int(fans_number)/20)
        # pages+1
        for index in range(1, pages):
            url = 'http://my.csdn.net/my/fans/{}'.format(index)
            response = self.session.get(url=url, headers=self.headers)
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')
                user_names = soup.find_all('a', {'class': 'user_name'})
                fans.extend([str(username.attrs['href']).lstrip('/') for username in user_names])
            else:
                raise Exception("獲取第{}頁數據失效".format(index))
        return fans

    def get_follow_number(self):
        url = 'http://my.csdn.net/{}'.format(self.domain)

        response = self.session.get(url=url, headers=self.headers)
        # print(response.text)
        if response.status_code == 200:
            soup = BeautifulSoup(response.text, 'html.parser')
            return soup.find('a', {'href': '/my/follow'}).get_text()
        else:
            return 0

    def get_follow(self):
        follows = []

        url = 'http://my.csdn.net/{}'.format(self.domain)
        follow_number = self.get_follow_number()
        pages = math.ceil(int(follow_number) / 20)
        # pages+1
        for index in range(1, pages):
            url = 'http://my.csdn.net/my/follow/{}'.format(index)
            response = self.session.get(url=url, headers=self.headers)
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')
                user_names = soup.find_all('a', {'class': 'user_name'})
                follows.extend([str(username.attrs['href']).lstrip('/') for username in user_names])
            else:
                raise Exception("獲取第{}頁數據失效".format(index))
        return follows




class ListUtils(object):
    """
    利用numpy 進行數據的篩選
    """
    def __init__(self):
        pass

    @staticmethod
    def comminInList(self, x=[], y=[]):
        return np.intersect1d(ar1=x, ar2=y, assume_unique=True)





if __name__ == '__main__':
    fans = Fans(domain='你的用戶名', password='你的密碼')
    # fans1 = fans.get_fans(username='marksinoberg')
    # result = ListUtils.comminInList(fans1, fans2)
    # print(result)
    follows = fans.get_follow()
    print(follows)




對照一下運行結果,關注人信息獲取如下。


關注人信息獲取

圖形化

圖形化需要借助matplotlib來畫圖,而載體就是networkx,所以我們需要對此進行安裝。在此不再過多敘述。

然后就是對于networkx的使用了。

步驟

一般有如下幾個步驟:

  • 聲明graph
  • 填充節點和邊
  • 畫出圖形

中文節點問題

默認的matplotlib 對于中文支持的不太友好。為了解決這一個問題,可以通過如下步驟實現。

  • 到matplotlib的安裝目錄下找到字體文件夾, 比如我的是
    C:\Users\biao\Desktop\network\env\Lib\site-packages\matplotlib\mpl-data\fonts\ttf

  • 然后從本地的字體庫(比如C:\Windows\Fonts\XX.ttf)中拷貝一份,重命名為DejaVuSans.ttf,放置到剛才的matplotlib字體文件夾下即可。為什么要這么做?答案就是matplotlib默認使用DejaVuSans.ttf

實戰

下面實戰一下CSDN的關注人和粉絲跟自己的關系演示。因為粉絲人數過多的話,會導致生成的圖片重疊度較大,所以這里選取前20個關注人和前20個粉絲。

import networkx as nx
import matplotlib.pyplot as plt
import spider


fans = spider.Fans(domain='你的用戶名', password='你的密碼')
fans_names = fans.get_fans()[:20]
follow_names = fans.get_follow()[:20]
nodes = fans_names
relations1 = [('我', username) for username in fans_names]
relations2 = [(username, '我') for username in follow_names]
colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple']
graph = nx.DiGraph()

graph.add_node('我')
graph.add_nodes_from(fans_names)
graph.add_edges_from(relations1)
graph.add_edges_from(relations2)
nx.draw(graph, with_labels=True,  hold=True, node_color=colors)
plt.title('CSDN 博客關注與粉絲圖形化顯示')
plt.axis('off')
plt.show()

生成的圖片如下:


“模擬社交網絡分析”

總結

對于networkx,這里講的并不是很多,也可以說就沒怎么講。這是因為官方文檔的卻是夠詳細了。而且越往深處看,越覺驚喜。基本上對于社交網絡的分析,它是一個很不錯的選擇了。

還有就是關于輪子,平時多寫一些可靠的輪子,說不一定哪天就用到了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容