Neo4j是一個高性能的NoSQL圖形數據庫(Graph Database),它將結構化數據存儲在網絡上而不是表中。它是一個嵌入式的、基於磁盤的、具有徹底的事務特性的Java持久化引擎,可是它將結構化數據存儲在網絡(從數學角度叫作圖)上而不是表中。Neo4j也能夠被看做是一個高性能的圖引擎,該引擎具備成熟數據庫的全部特性。
做爲圖形數據庫,Neo4j最讓人驚喜的功能就是它能夠直觀地展現圖,也就是節點與節點之間的關係,固然,它還有其它的優點,好比:html
在本文中,筆者但願可以經過一個簡單的例子來展現Neo4j的使用以及它的強大之處,這無疑更適合於初學者,由於筆者也是剛入門。
如下,筆者並不會過多地介紹Neo4j的操做,只是但願讀者能對Neo4j的功能有直觀的感覺,至於教程之類的,能夠參考文章最後的參考文獻。
下面,讓咱們進入本次的Neo4j之旅~前端
因爲《流浪地球》的大熱以及筆者對此的欣賞,所以,這次的項目爲分析中國電影票房排行。咱們的數據來自於百度百科,用爬蟲
獲得咱們須要的數據,主要是電影的相關信息,如排名,票房,上映日期等,以及電影的主演。將數據儲存爲CSV文件,並導入至Neo4j,最後獲得電影的簡單分析及可視化。
整個項目主要是如下三步:node
其中,Py2neo爲Neo4j的Python接口。
整個項目的結構以下圖:python
接下來,筆者將詳細地介紹每一步的操做及代碼,let's go ~git
數據的獲取始終是一個重要的問題,好在咱們有爬蟲這個工具。爲了可以展現中國電影票房排行中的電影信息以及演員與電影的關係,首先的重要一步就是獲取咱們須要的須要。
咱們須要兩份數據。第一份數據,就是中國電影票房排行數據,網址爲:https://baike.baidu.com/item/...,頁面以下:github
咱們製做爬蟲,將這個表格爬取下來,並將表格的第一行(字段名稱)做爲電影的相關信息,而後儲存爲movies.csv。整個過程的Python代碼(movie.py)以下:(由於這是公開數據,這個爬蟲是合理的。)web
# -*- 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中的數據以下:算法
OK,第二份數據,每部電影(共20部)的主演,以《流浪地球》爲例,網址爲:https://baike.baidu.com/item/...,頁面以下:數據庫
咱們只須要爬取每部電影的主演就夠了,也就是上圖中的紅色部分,實現的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數據以下:
OK,數據收集的任務就到此完成了,有了爬蟲,輕鬆搞定數據難題。
接着,咱們須要用到剛纔儲存的movies.csv和actor.csv,利用Py2neo來將數據導入至Neo4j中。
首先,須要確保你的電腦已安裝好Neo4j,Py2neo,並開啓了Neo4j服務,具體的安裝流程可參考網址:https://www.w3cschool.cn/neo4... 。
利用Py2neo,咱們就能夠用Python輕鬆地實現將數據導入至Neo4j,實現的功能爲:建立電影節點以及演員節點,並建立二者之間的關係,關係名稱爲「ACT_IN」。實現的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服務 graph = Graph(host="localhost://7474", auth=("neo4j", "jc147369")) # 建立電影節 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!') # 建立演員節點 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!') # 建立演員——電影關係 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服務,不出意外,那麼你的Neo4j已經默默地儲存了這些數據,而它們將會給出帶來巨大的驚喜:天吶,這居然是個數據庫!
在瀏覽器中輸入「localhost:7474」,並點擊左上方的數據庫圖標,就能看到下圖:
能夠看到,在Neo4j中,咱們建立了142個節點,分爲兩類:Movie和Actor,以及136對關係,關係名稱爲ACT_IN. 固然,這些都是枯燥的,那麼咱們來看看數據展現這步吧,它會給咱們帶來什麼驚喜?
好不容易到了數據展現這一步,以前的努力都不會白費!
在Neo4j的前端頁面(也就是網址:http://localhost:7474)中的命令行中輸入命令:
MATCH (Movie) RETURN (Movie);
運行命令後,很快就能獲得整個圖(包含電影節點、演員節點以及關係)的可視化展現,因爲圖像過大,不能看清細節,所以,就局部放大來看,同時獲得一些簡單的分析。
首先是圖一,吳京主演的電影。
在中國電影票房排行榜的前20名中,吳京主演了《戰狼2》與《流浪地球》,且二者沒有其餘更多的相同主演。
接着是圖二,沈騰主演的電影。
在中國電影票房排行榜的前20名中,沈騰主演了《西虹市首富》、《瘋狂的外星人》以及《羞羞的鐵拳》,這顯示了沈騰的票房號召力(他也是筆者喜歡的喜劇演員),不過開心麻花團隊的其餘成員在這三部電影的拍攝中應該見不到面。
接着是圖三,《捉妖記》及《捉妖記2》。
捉妖記系列電影無疑是成功的,兩部電影都進了票房的前20,他們的共同主演就多了,有曾志偉,吳君如,井柏然,白百何。
接着是圖四,主要是看看Neo4j幫咱們挖掘了哪些潛在的關係。
從《唐人街探案2》到《捉妖記2》,這個不算長的鏈條給了咱們一些驚喜,原來,劉昊然能夠經過尚語賢再經過曾志偉認識李宇春,一個very interesting的分析。固然,這個是筆者的分析,他倆到底認不認識筆者是不知道滴~
分析到此結束,若是讀者想看原圖,能夠參看該項目的github地址:https://github.com/percent4/N... 。
感謝讀者不厭其煩地看到了這裏,看完了這篇「又臭又長」的文章,好在圖比較多,應該能稍微減輕點閱讀的壓力。
再說說該項目的不足之處:那就是Neo4j的操做語法展現的比較少,約等於沒有,這主要是筆者也是初入門,不熟。若是後續對Neo4j的操做語法CQL熟練了,咱們就能能到更多有趣的結果,而不是這麼一句簡單的分析(有敷衍的嫌疑)。
最後,對此項目感興趣的讀者,能夠移步該項目的github地址:https://github.com/percent4/N... 。
注意:不妨瞭解下筆者的微信公衆號: Python爬蟲與算法(微信號爲:easy_web_scrape), 歡迎你們關注~