多虧學了這個Python庫,一晚上端掉了一個傳銷團伙...
“這是從他們窩點電腦里導出的一份數據,你先看看能不能找出什么端倪,我再去找幾個人問問話。”
王隊丟給我一個u盤,拿起飯盒胡亂塞了幾口飯,便拎起帽子快步走出了辦公室。
今晚我們根據情報,前往一處傳銷窩點實施了抓捕行動,帶回來了十幾個人。
但現場沒有發現什么重要證據,抓到的幾個人也都緘口不言,現在沒法知道他們是否還有其他的窩點,也不知道他們的上線是誰人在哪里,行動一時陷入了僵局。
而此時我手中的這份文件,可能會成為破局的關鍵。
我開始觀察起這份人員名單:invite_id字段是不重復的,應該和人名是一對一的關系;而invited_id重復的很多,而且基本都是在invite_id出現過的數據。
所以我們基本可以推斷出,這是一份記錄傳銷組織上下線關系的名單。數據足有數百條之多,可見這是一個不小的犯罪組織。
不到一個小時的功夫,王隊回來了。
“沒用,還是死鴨子嘴硬。”王隊一屁股坐在椅子上,看了一眼時間,已經快到十二點了。“那份數據看的怎么樣了,有沒有找到什么線索?”
“這是一個很大的組織,總成員數有好幾百,我們現在可能只抓到了冰山一角啊。”
“你說的沒錯,但正因如此,我們現在必須抓緊時間。”王隊走到我的工位前,“我們現在的任務是先找到他們的上線,擒賊先擒王。但今晚抓到的這群人都審不出東西來,雖然能確定他們的身份,暫時也還是確定不了他們之間的關系啊。”
“你說他們之間的關系?”我突然想起前段時間看到的networkx這個python庫,這次說不定能派上用場。“交給我了,給我五分鐘時間。”
首先用pandas導入文件中的數據,并篩選出我們需要的部分:
df = pd.read_excel('./doc/1_evidence.xls')
df = df.loc[:, ['id','name','invite_id','invited_id']]
df.columns = ['id','title','to', 'from']
然后調用networkx庫,生成層級關系圖并導出:
G = nx.from_pandas_edgelist(df, 'from', 'to', create_using=nx.DiGraph())
nt = net.Network('960px', '1280px', directed=True)
nt.from_nx(G)
nt.show('1_evidence.html')
這樣我就得到了這份文件對應的層級關系圖,上下線關系瞬間一目了然了:
一瞬間王隊面露喜色,但立馬又恢復了嚴肅:“你這個是不是有點華而不實啊,雖然看著挺直觀,但你能從里面找到誰是這個組織的最上級嗎?”
這當然難不倒我,最上級也就是圖中網絡的根節點,必然是沒有其他的點指向它的,所以我們只要遍歷所有節點,找到入度為0的點就可以了。
# 找到根節點
top_node = []
for node, degrees in G.in_degree():
if degrees == 0:
top_node.append(node)
print('Big Boss:', top_node)
“Big Boss: [100000]” 屏幕上出現了這樣的輸出。“100000這個編號在表中沒有對應的人,但100000下只有一個編號162385的下線,他應該就是這個組織的頭頭了。”
“不錯,要的就是這個!我去讓其他同事找這個人的信息,你繼續研究數據,把和這個人走的近的人全部找出來!”
這想必也不是難題,既然根節點已經找到了,我們便可以得到所有節點各自所在的層數。
# 設置所有節點級別
l = nx.shortest_path_length(G, 100000)
nx.set_node_attributes(G, l, 'level')
# 計算每級人員數目
data = {}
for node, level in l.items():
if level in data.keys():
data[level].append(node)
else:
data[level] = [node]
for level, nodes in data.items():
print(level, len(nodes))
這個組織竟然已經足足發展了36層,想想真是讓人直冒冷汗,還好我的同事及時發現了。
然后根據層級給節點標注顏色,方便觀察:
# 添加顏色
for node in G.nodes:
G.nodes[node]['title'] = str(node)
level = G.nodes[node]['level']
if level == 0:
G.nodes[node]['color'] = 'red'
elif level == 1:
G.nodes[node]['color'] = 'orange'
elif level == 2:
G.nodes[node]['color'] = 'yellow'
可以看到這個編號162385的人,自己只有兩個下線,而這兩個下線每人都各自另外發展了幾十個下線,想想還蠻有意思。
“找到了!”王隊撞開辦公室的門,“那個人找到了,就在今晚逮捕的這群人里面,還有兩個他的下線也在里面。他們也都承認了,現在正在重點審。”看來實際情況和我的推測完全相符,多虧了這份名單。
“你今晚立了件大功啊!”王隊走過來拍了拍我的肩膀。“不過現在還沒完,根據他們的口供,文件里的就是他們組織的全部人員信息了。你現在把他們發展下線最多的幾個人給我找出來,我們根據信息,立刻安排定點抓捕行動。”
跟前面的差不多,不過這次我需要遍歷所有節點的出度數,然后按倒序排序,取前幾項就可以了。
# 給下線前十的目標添加顏色
degrees = G.out_degree()
top_nodes = sorted(degrees, key=lambda x: x[1], reverse=True)[:10]
print(top_nodes)
for node in top_nodes:
G.nodes[node[0]]['color'] = 'green'
然后給目標節點加上顏色,方便觀察,最終得到了這樣的關系圖:
“干得不錯,只要再把這幾個人抓到,就相當于切斷了這個組織的大動脈,后面的慢慢收尾就可以了。”王隊把文件合上,笑著對我說。“沒想到你還有這本事,真是后生可畏啊!”
“今天抓到的那三條大魚,現在審出什么結果了?”相對于其他,我還是對案情本身更感興趣。
“別提了,都快笑死我了。這仨人看見證據直接慌了神,開始互相推卸責任,老大說同伙全是另外兩個人拉來的他都沒參與,另外倆人說騙局全是老大策劃的他們就是手下打工的,現在估計還吵著呢...”