1. 程式人生 > >小型動漫知識圖譜的構建 (Python+Neo4j) (純實踐內容,基於bilibili所有正版番劇的動漫、聲優、角色、型別)

小型動漫知識圖譜的構建 (Python+Neo4j) (純實踐內容,基於bilibili所有正版番劇的動漫、聲優、角色、型別)

資料來源:bilibili所有番劇的詳情頁面的資訊,共計3000+的番劇

(已經整理好的資料和程式碼下文有連結)

 

步驟1:抽取資訊

從各個詳情頁面中抽取資訊,比如動漫這個節點的檔案,大概內容如下

這一步稍微有些麻煩的地方就是爬蟲的時候資料可能會出現清理不乾淨的情況,比如某個name的前面或者後面有空格、換行符等奇怪的字元,會對後面建立relation的表產生很多麻煩,注意資料要清理乾淨。

 

 

 

步驟2:關係分類

先理清所有節點和關係,比如相對本文的動漫資訊而言,關係如下

雖然這裡的關係是有箭頭的,但是本文所用的NOSQL資料庫為neo4j,neo4j中的關係都是雙向的關係,可以自行將start_id和end_id進行調換測試。

 

 

 

步驟3:生成所有關係和節點CSV檔案

neo4j最方便的地方在於可以在CSV檔案中保留好對應關係,然後直接匯入資料庫,所以要把我們當前需要的四個節點以及四個關係,一共八個CSV檔案生成完畢。

下面是細節性的一些關鍵問題:

 

1.所有的節點檔案,第一列都要為“index:ID”,最後一列都要為":LABEL" , 中間所有列即為這個實體的屬性。注意實體屬性最好不要用中文,label即為這個實體的對應標籤。

 

2.所有的關係檔案,第一列都要為“:START_ID”,第二列都要為":END_ID",第三列要為"relation",第四列要為":TYPE" , start_id對應一個節點的index_id,end_id對應另一個節點的end_id,relation即為兩者的關係,type即為標籤,一般type和relation內容相同

 

3.不管是實體還是關係檔案裡的index_id還是end_id,請一開始設一個比你資料規模大出兩個數量級的初始值,比如本文的所有id都是100000+i,因為主鍵設的太小容易造成不同檔案的主鍵混淆,巨坑注意。

 

4.不推薦實體和關係檔案同時生成,一開始我想省時間貪便宜一個函式試圖解決兩個實體三個關係,後來中途出了各種意想不到的問題,比如實體主鍵重複,實體資料清洗不夠完全等等問題,而且當資料量巨大的時候,有些網站反爬蟲機制很強經常出現IP被封或者伺服器主動斷開連線問題的時候,自身的異常處理沒有做到位,斷點續爬也沒做好,一切都要重來。所以,建議先把所有必要資料先收集完畢,混亂也無所謂,然後再進行資料處理。

 

 

 

步驟4:匯入neo4j資料庫

匯入資料庫的語法很簡單,相對於本文而言,只需開啟neo4j的bin目錄,輸入以下內容即可

neo4j-admin import --mode=csv --database=anime.db --nodes importdata\anime\animes.csv --nodes importdata\anime\catagorys.csv --nodes importdata\anime\characters.csv --nodes importdata\anime\voice_actors.csv --relationships importdata\anime\anime_and_character_releation.csv --relationships importdata\anime\anime_and_voice_actor_releation.csv --relationships importdata\anime\anime_type.csv --relationships importdata\anime\character_and_voice_releation.csv

 

--mode=csv,指定為csv模式

 

--database=anime.db ,指定資料庫,這裡又是一個坑,neo4j不方便直接在頁面上切換資料庫,要生成新的資料庫你必須要去conf檔案修改預設配置,而這裡指定的資料庫如果匯入失敗的話有時候也會自動生成,你需要親手去data檔案裡把生成的資料庫檔案刪除然後再次進行匯入,不然會報資料庫已經存在的錯誤。

 

--nodes + 檔案 ,為匯入節點,檔案路徑的根目錄預設為neo4j/bin,請把csv檔案放在你指定的目錄下。

 

-- relationship + 檔案 ,同理

 

 

 

步驟5:cypher語句的編寫

cypher語句作為neo4j的查詢語句,極其人性化便於使用,入門中文文件連結如下

http://neo4j.com.cn/public/cypher/default.html

 

下面將對動漫知識圖譜來做一下實際的查詢

 

1.刀劍神域第二季出演的所有聲優

 

Cypher語句:MATCH p = (a:Anime)-[r:`出演聲優`]->() where a.name=~"刀劍神域.+" return p

 

 

2.我的英雄學院三季中所有的角色

 

Cypher語句:MATCH p=(a:Anime)-[r:`擁有角色`]->() where a.name=~"我的英雄學院.+" RETURN p

 

 

 

3.花澤香菜出演的所有動漫角色

 

Cypher語句:match (p:voice_actor{name:'花澤香菜'})--(b:character) return p,b

 

 

4.查詢跟一部動漫相關的所有關係:

《我的英雄學院》三季+OAD 所有關係

Cypher語句:match p=(a:Anime)-[r]->() where a.name=~"我的英雄.+" return p

 

5.《刀劍神域第二季》所有關係

 

Cypher語句:match p=(a:Anime)-[r]->() where a.name=~"刀劍神域.+" return p

 

6.兩個節點之間的最短路徑

 

阿良良木歷君和折原臨也的關係,最短關係就是同時都是神谷浩史配音

Cypher語句:match (a:character{name:"折原臨也"}),(b:character{name:"阿良良木歷"}),r=shortestPath((a)-[*..3]-(b)) return r

 

 

 

7.兩個節點間的關聯深度增加

 

Cypher語句:match r = (a:character{name:"折原臨也"})-[*..3]-(b:character{name:"阿良良木歷"}) return r

3為關聯的深度

折原臨也是無頭騎士異聞錄中的人物

阿良良木歷是物語系列中的人物

而神谷浩史同時參與了兩部作品的配音工作

所以關聯的深度為3!

 

實現過程中的踩過的部分坑如下(僅供參考):

1.多執行緒運作時,務必不要將寫入操作和爬蟲請求寫在一起,死鎖可能造成error,然後全部GG

2.四核電腦(相對於本機而言)執行緒數最好不要超過32,不然容易死鎖效率也無法提升,有的時候根本沒必要多執行緒的時候就別用,先自己測試一下效率再考慮是否用多執行緒

3.先將爬蟲資料儲存csv,然後通過csv再建立關係,原因同上

4.ThreadPool務必注意將map的key函式改成傳參模式,將寫入操作把列表加上全域性變數宣告,寫在key的函式內

5.前端資料注意先測試幾組資料再總體爬蟲,防止前端內容不一致的錯誤導致正則出錯,比如':'和':'和多餘的"\\t" "\n"等等

6.相對於bilibili而言,要注意爬取的是json中的media_id而不是播放頁面的play引數,兩者差異巨大容易混淆

7.相對於bilibili而言,反爬蟲機制弱到幾乎沒有(但用一),但還是要注意異常處理和請求超時、請求間隔

8.Http_header可有可無(限bilibili,但長期請求過多頻率過快也會被封IP),看心情

9.neo4j的中文預設編碼為utf8無bom模式,程式內無法解決編碼問題就去文件修改編碼

10.python編碼出現問題必要時候可以轉換成raw_unicode_escape編碼再進行encode

11.關係和節點最好不要一起建,因為節點如果屬性只有一個的話可能會重複,MD

 

相關檔案和程式碼的連結如下:

程式碼風格混亂內容辣雞僅供參考,檔案經過測試可以使用

https://download.csdn.net/download/shr903988854/10729235