Neo4j入門之中國電影票房排行淺析

什么是Neo4j?

??Neo4j是一個高性能的NoSQL圖形數(shù)據(jù)庫(Graph Database),它將結(jié)構(gòu)化數(shù)據(jù)存儲在網(wǎng)絡(luò)上而不是表中薪捍。它是一個嵌入式的笼痹、基于磁盤的、具備完全的事務(wù)特性的Java持久化引擎酪穿,但是它將結(jié)構(gòu)化數(shù)據(jù)存儲在網(wǎng)絡(luò)(從數(shù)學角度叫做圖)上而不是表中凳干。Neo4j也可以被看作是一個高性能的圖引擎,該引擎具有成熟數(shù)據(jù)庫的所有特性被济。
??作為圖形數(shù)據(jù)庫救赐,Neo4j最讓人驚喜的功能就是它可以直觀地展示圖,也就是節(jié)點與節(jié)點之間的關(guān)系只磷,當然经磅,它還有其它的優(yōu)勢泌绣,比如:

  • 很容易表示連接的數(shù)據(jù);
  • 檢索/遍歷/導航更多的連接數(shù)據(jù)是非常容易和快速的预厌;
  • 能輕松地表示半結(jié)構(gòu)化數(shù)據(jù)阿迈;
  • Neo4j CQL查詢語言命令類似于SQL,可讀性好配乓,容易學習仿滔;
  • 使用簡單而強大的數(shù)據(jù)模型;
  • 不需要復雜的連接來檢索連接的/相關(guān)的數(shù)據(jù)犹芹。

??在本文中崎页,筆者希望能夠通過一個簡單的例子來展示Neo4j的使用以及它的強大之處,這無疑更適合于初學者腰埂,因為筆者也是剛?cè)腴T飒焦。
??以下,筆者并不會過多地介紹Neo4j的操作屿笼,只是希望讀者能對Neo4j的功能有直觀的感受牺荠,至于教程之類的,可以參考文章最后的參考文獻驴一。
??下面休雌,讓我們進入本次的Neo4j之旅~

項目展示

??由于《流浪地球》的大熱以及筆者對此的欣賞,因此肝断,此次的項目為分析中國電影票房排行颁井。我們的數(shù)據(jù)來自于百度百科夏块,用爬蟲得到我們需要的數(shù)據(jù)壕鹉,主要是電影的相關(guān)信息雏赦,如排名,票房趣钱,上映日期等涌献,以及電影的主演。將數(shù)據(jù)儲存為CSV文件首有,并導入至Neo4j燕垃,最后得到電影的簡單分析及可視化。
??整個項目主要是以下三步:

  • 數(shù)據(jù)獲染:利用爬蟲實現(xiàn)利术;
  • 數(shù)據(jù)導入:利用Py2neo實現(xiàn);
  • 數(shù)據(jù)展示:利用Neo4j實現(xiàn)低矮。

其中,Py2neo為Neo4j的Python接口被冒。
??整個項目的結(jié)構(gòu)如下圖:

電影票房項目

??接下來军掂,筆者將詳細地介紹每一步的操作及代碼轮蜕,let's go ~

數(shù)據(jù)獲取

??數(shù)據(jù)的獲取始終是一個重要的問題,好在我們有爬蟲這個工具蝗锥。為了能夠展示中國電影票房排行中的電影信息以及演員與電影的關(guān)系跃洛,首先的重要一步就是獲取我們需要的需要。
??我們需要兩份數(shù)據(jù)终议。第一份數(shù)據(jù)汇竭,就是中國電影票房排行數(shù)據(jù),網(wǎng)址為:https://baike.baidu.com/item/%E4%B8%AD%E5%9B%BD%E7%94%B5%E5%BD%B1%E7%A5%A8%E6%88%BF/4101787?fr=aladdin穴张,頁面如下:

中國電影票房_百度百科

??我們制作爬蟲细燎,將這個表格爬取下來,并將表格的第一行(字段名稱)作為電影的相關(guān)信息皂甘,然后儲存為movies.csv玻驻。整個過程的Python代碼(movie.py)如下:(因為這是公開數(shù)據(jù),這個爬蟲是合理的偿枕。)

# -*- coding: utf-8 -*-

import requests
import pandas as pd
from bs4 import BeautifulSoup

url = "https://baike.baidu.com/item/%E4%B8%AD%E5%9B%BD%E7%94%B5%E5%BD%B1%E7%A5%A8%E6%88%BF/4101787"
# 請求頭部
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
r = requests.get(url, headers=headers)
soup = BeautifulSoup(r.text.encode('ISO-8859-1'),'lxml')
table = soup.find('table')('tr')

movies = []
for line in table[1:]:
   movie = {'rank': int(line('td')[0].text),
                 'src': line('td')[1]('a')[0]['href'],
                 'name': line('td')[1].text,
                 'box_office': line('td')[2].text,
                 'avg_price': int(line('td')[3].text),
                 'avg_people': int(line('td')[4].text),
                 'begin_date': line('td')[5].text.strip(),
                 }
   # print(movie)
   movies.append(movie)

# print(movies)

df = pd.DataFrame({'rank': [movie['rank'] for movie in movies],
                  'src': [movie['src'] for movie in movies],
                  'name': [movie['name'] for movie in movies],
                  'box_office': [movie['box_office'] for movie in movies],
                  'avg_price': [movie['avg_price'] for movie in movies],
                  'avg_people': [movie['avg_people'] for movie in movies],
                  'begin_date': [movie['begin_date'] for movie in movies]
                  })
# print(df.head())
df.to_csv(r'./movies.csv', index=False)

??movies.csv中的數(shù)據(jù)如下:

movies.csv

??OK璧瞬,第二份數(shù)據(jù),每部電影(共20部)的主演渐夸,以《流浪地球》為例嗤锉,網(wǎng)址為:https://baike.baidu.com/item/%E6%B5%81%E6%B5%AA%E5%9C%B0%E7%90%83/16278407,頁面如下:

流浪地球

我們只需要爬取每部電影的主演就夠了墓塌,也就是上圖中的紅色部分瘟忱,實現(xiàn)的Python代碼(actor.py)如下:

# -*- coding: utf-8 -*-

import requests
import pandas as pd
from bs4 import BeautifulSoup

def get_actors(src):
    url = "https://baike.baidu.com"+src
    # 請求頭部
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
    r = requests.get(url, headers=headers)
    soup = BeautifulSoup(r.text.encode('ISO-8859-1'),'lxml')
    names = soup.find_all('dt', class_="basicInfo-item name")
    values = soup.find_all('dd', class_="basicInfo-item value")

    actors = []
    for name, value in zip(names, values):
        # print(name.text)
        if '主' in name.text and '演' in name.text:
            # print(name.text.replace('    ', ''), value.text)
            actors = value.text.strip().split(',')
            actors = [actor.strip().replace('\xa0', '').replace('\n[6]', '') for actor in actors if actor]
    # print(actors)
    return '桃纯,'.join(actors)

df = pd.read_csv('./movies.csv')

actors_list = []
for name, src in zip(list(df['name']), list(df['src'])):

    actors = get_actors(src)
    # print(name, actors)
    actors_list.append(actors)

new_df = pd.DataFrame({'actors': actors_list})
new_df['name'] = df['name']
# print(new_df)
new_df.to_csv(r'./actors.csv', index=False)

??生成的actor.csv數(shù)據(jù)如下:

actor.csv

??OK酷誓,數(shù)據(jù)收集的任務(wù)就到此完成了,有了爬蟲态坦,輕松搞定數(shù)據(jù)難題盐数。

導入數(shù)據(jù)

?? 接著,我們需要用到剛才儲存的movies.csv和actor.csv伞梯,利用Py2neo來將數(shù)據(jù)導入至Neo4j中玫氢。
?? 首先,需要確保你的電腦已安裝好Neo4j谜诫,Py2neo漾峡,并開啟了Neo4j服務(wù),具體的安裝流程可參考網(wǎng)址:https://www.w3cschool.cn/neo4j/neo4j_features_advantages.html 喻旷。
?? 利用Py2neo生逸,我們就可以用Python輕松地實現(xiàn)將數(shù)據(jù)導入至Neo4j,實現(xiàn)的功能為:創(chuàng)建電影節(jié)點以及演員節(jié)點,并創(chuàng)建兩者之間的關(guān)系槽袄,關(guān)系名稱為“ACT_IN”烙无。實現(xiàn)的Python代碼()如下:

# -*- coding: utf-8 -*-

import pandas as pd
from py2neo import Graph, Node, Relationship, NodeMatcher

# 讀取csv文件
movies_df = pd.read_csv(r'./movies.csv')
actors_df = pd.read_csv(r'./actors.csv')

# 連接Neo4j服務(wù)
graph = Graph(host="localhost://7474", auth=("neo4j", "jc147369"))

# 創(chuàng)建電影節(jié)
for i in range(movies_df.shape[0]):
    rank = str(movies_df.iloc[i, :]['rank'])
    name = movies_df.iloc[i, :]['name']
    box_office = movies_df.iloc[i, :]['box_office']
    avg_price = str(movies_df.iloc[i, :]['avg_price'])
    avg_people = str(movies_df.iloc[i, :]['avg_people'])
    begin_date = movies_df.iloc[i, :]['begin_date']
    
    node = Node("Movie", 
                name=name,
                rank=rank,
                box_office=box_office,
                avg_price=avg_price,
                avg_people=avg_people,
                begin_date=begin_date
                )
    # print(movies_df.iloc[i, :]['rank'])
    graph.create(node)

print('create movie nodes successfully!')

# 創(chuàng)建演員節(jié)點
all_actors = set()
for i in range(actors_df.shape[0]):
    actor_list = actors_df.iloc[i, :]['actors'].split(',')
    for actor in actor_list:
        all_actors.add(actor)
 
for actor in all_actors:
    node = Node("Actor", name=actor)
    graph.create(node)

print('create actor nodes successfully!')

# 創(chuàng)建演員——電影關(guān)系
for i in range(actors_df.shape[0]):
    name = actors_df.iloc[i, :]['name']
    matcher = NodeMatcher(graph)
    movie_node = matcher.match("Movie", name=name).first()
    actors = actors_df.iloc[i, :]['actors'].split('遍尺,')
    # print(name, actors)
    for actor in actors:
        actor_node = matcher.match("Actor", name=actor).first()
        relationship = Relationship(actor_node, 'ACT_IN', movie_node)
        graph.create(relationship)

print('create relationships successfully!')
print('You can check Neo4j now!')

??只要你的電腦已安裝好Neo4j截酷,Py2neo,并開啟了Neo4j服務(wù)乾戏,不出意外迂苛,那么你的Neo4j已經(jīng)默默地儲存了這些數(shù)據(jù),而它們將會給出帶來巨大的驚喜:天吶鼓择,這竟然是個數(shù)據(jù)庫三幻!
??在瀏覽器中輸入“l(fā)ocalhost:7474”,并點擊左上方的數(shù)據(jù)庫圖標惯退,就能看到下圖:

數(shù)據(jù)儲存好了嗎赌髓?

??可以看到,在Neo4j中催跪,我們創(chuàng)建了142個節(jié)點锁蠕,分為兩類:Movie和Actor,以及136對關(guān)系懊蒸,關(guān)系名稱為ACT_IN. 當然荣倾,這些都是枯燥的,那么我們來看看數(shù)據(jù)展示這步吧骑丸,它會給我們帶來什么驚喜舌仍?

數(shù)據(jù)展示

??好不容易到了數(shù)據(jù)展示這一步,之前的努力都不會白費通危!
??在Neo4j的前端頁面(也就是網(wǎng)址:http://localhost:7474)中的命令行中輸入命令:

MATCH (Movie)
RETURN (Movie);

運行命令后铸豁,很快就能得到整個圖(包含電影節(jié)點、演員節(jié)點以及關(guān)系)的可視化展示菊碟,由于圖像過大节芥,不能看清細節(jié),因此逆害,就局部放大來看头镊,同時得到一些簡單的分析。
??首先是圖一魄幕,吳京主演的電影相艇。

圖一

在中國電影票房排行榜的前20名中,吳京主演了《戰(zhàn)狼2》與《流浪地球》纯陨,且兩者沒有其他更多的相同主演坛芽。
??接著是圖二留储,沈騰主演的電影。

圖二

在中國電影票房排行榜的前20名中靡馁,沈騰主演了《西虹市首富》欲鹏、《瘋狂的外星人》以及《羞羞的鐵拳》,這顯示了沈騰的票房號召力(他也是筆者喜歡的喜劇演員)臭墨,不過開心麻花團隊的其他成員在這三部電影的拍攝中應(yīng)該見不到面。
??接著是圖三膘盖,《捉妖記》及《捉妖記2》胧弛。

圖三

捉妖記系列電影無疑是成功的,兩部電影都進了票房的前20侠畔,他們的共同主演就多了结缚,有曾志偉,吳君如软棺,井柏然红竭,白百何。
??接著是圖四喘落,主要是看看Neo4j幫我們挖掘了哪些潛在的關(guān)系茵宪。

圖四

從《唐人街探案2》到《捉妖記2》,這個不算長的鏈條給了我們一些驚喜瘦棋,原來稀火,劉昊然可以通過尚語賢再通過曾志偉認識李宇春,一個very interesting的分析赌朋。當然凰狞,這個是筆者的分析,他倆到底認不認識筆者是不知道滴~

??分析到此結(jié)束沛慢,如果讀者想看原圖赡若,可以參看該項目的github地址:https://github.com/percent4/Neo4j_movie_demo

總結(jié)

??感謝讀者不厭其煩地看到了這里团甲,看完了這篇“又臭又長”的文章逾冬,好在圖比較多,應(yīng)該能稍微減輕點閱讀的壓力伐庭。
??再說說該項目的不足之處:那就是Neo4j的操作語法展示的比較少粉渠,約等于沒有,這主要是筆者也是初入門圾另,不熟霸株。如果后續(xù)對Neo4j的操作語法CQL熟練了,我們就能能到更多有趣的結(jié)果集乔,而不是這么一句簡單的分析(有敷衍的嫌疑)去件。
??最后坡椒,對此項目感興趣的讀者,可以移步該項目的github地址:https://github.com/percent4/Neo4j_movie_demo 尤溜。

注意:不妨了解下筆者的微信公眾號: Python爬蟲與算法(微信號為:easy_web_scrape)倔叼, 歡迎大家關(guān)注~

參考文獻

  1. Neo4j_百度百科:https://baike.baidu.com/item/Neo4j/9952114?fr=aladdin
  2. neo4j教程:https://www.w3cschool.cn/neo4j/neo4j_features_advantages.html
  3. The Py2neo v3 Handbook: https://py2neo.org/v3/index.html
  4. Neo4j簡介及Py2Neo的用法: https://cuiqingcai.com/4778.html
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宫莱,隨后出現(xiàn)的幾起案子丈攒,更是在濱河造成了極大的恐慌,老刑警劉巖授霸,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巡验,死亡現(xiàn)場離奇詭異,居然都是意外死亡碘耳,警方通過查閱死者的電腦和手機显设,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辛辨,“玉大人捕捂,你說我怎么就攤上這事《犯悖” “怎么了指攒?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長榜旦。 經(jīng)常有香客問我幽七,道長,這世上最難降的妖魔是什么溅呢? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任澡屡,我火速辦了婚禮,結(jié)果婚禮上咐旧,老公的妹妹穿的比我還像新娘驶鹉。我一直安慰自己,他們只是感情好铣墨,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布室埋。 她就那樣靜靜地躺著,像睡著了一般伊约。 火紅的嫁衣襯著肌膚如雪姚淆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天屡律,我揣著相機與錄音腌逢,去河邊找鬼。 笑死超埋,一個胖子當著我的面吹牛搏讶,可吹牛的內(nèi)容都是我干的佳鳖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼媒惕,長吁一口氣:“原來是場噩夢啊……” “哼系吩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起妒蔚,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤穿挨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后面睛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體絮蒿,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年叁鉴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佛寿。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡幌墓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冀泻,到底是詐尸還是另有隱情常侣,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布弹渔,位于F島的核電站胳施,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肢专。R本人自食惡果不足惜舞肆,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望博杖。 院中可真熱鬧椿胯,春花似錦、人聲如沸剃根。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狈醉。三九已至廉油,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苗傅,已是汗流浹背抒线。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留金吗,地道東北人十兢。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓趣竣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親旱物。 傳聞我的和親對象是個殘疾皇子遥缕,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容