python在线爬取数据导入Neo4j创建知识图谱

本文介绍使用Neo4j和Python爬虫技术构建豆瓣Top250电影知识图谱的过程,涵盖图谱设计、数据爬取及图谱展示,旨在通过country、type、time等维度检索电影信息。
摘要由CSDN通过智能技术生成

近期学习Neo4j,以豆瓣top250数据为研究对象,实现python在线爬取数据写入Neo4j创建知识图谱,下文详细介绍步骤。

1、知识图谱设计

通过分析网页,爬取网页可以得到movie、country、type、time、director、actor、score等信息,此处我将movie、country、type、time、director、actor作为节点,而score作为movie的属性,网上有很多地方讲到只将movie、director、actor作为节点,其余均作为movie的属性,这个我之前也做过,但最后的效果并不是我想要的,至于什么效果,后文会提到。节点和关系设计如下图。

2、爬取数据并写入Neo4j

此处就直接上代码了:

from bs4 import BeautifulSoup
from urllib.request import urlopen,urlparse,urlsplit,Request
import urllib.request
import re
import codecs
import random
import py2neo
from py2neo import Graph
#
ua_list = [
    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36",#Chrome
    "Mozilla/5.0 (Windows NT 6.1; rv:40.0) Gecko/20100101 Firefox/40.0",#firwfox
    "Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",#IE
    "Opera/9.99 (Windows NT 5.1; U; zh-CN) Presto/9.9.9",#Opera
]

if __name__ == "__main__":
    # connect to graph
    graph = Graph (
        "http://localhost:11010/",
        username="admin",
        password="password"
    )
    for i in range(0,9):
        ua = random.choice( ua_list )
        url = 'https://movie.douban.com/top250?start='+str(i*25)+'&filter='
        req = urllib.request.Request( url, headers={'User-agent' : ua} )
        html=urlopen(req).read()
        soup = BeautifulSoup ( html, 'lxml' )
        page=soup.find_all('div', {'class' : 'item'})
        punc = ':· - ...:-'
        list_item=[]
        for item in page:
            content = {}
            try :
                text0=item.find ( 'p', {'class' : ""} ).text.strip ( ).split ( '\n' )[0]
                text1=item.find ( 'p', {'class' : ""} ).text.strip ( ).split ( '\n' ) [1]
                #get film
                film=item.find( 'span', {'class' : 'title'} ).text.strip ( )
                film=re.sub ( r"[%s]+" % punc, "", film.strip ( ) )
                # get score
                score=item.find ( 'span', {'class' : 'rating_num'} ).text.strip ( )
                graph.run (
                    "CREATE (movie:Movie {name:'" + film + "', score:'" + score +"'})" )
                #get director
                directors=text0.strip().split('   ')[0].strip().split(':')[1]
                directors = re.sub ( r"[%s]+" % punc, "", directors.strip ( ) )#存在特殊字符需要先去除
                # director=directors.split ( '/' )
                if len ( directors.split ( '/' ))>1:
                    print(film+'has more than one director')
                #创建director节点
                if directors not in list_item:
                    graph.run (
                        "CREATE (director:Person {name:'" + directors + "'})" )
                    list_item.append ( directors )
                #创建director-movie关系
                graph.run (
                    "match (p:Person{name:'" + directors + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (p)-[:directed]->(b)" )
                 #get actor
                actors = text0.strip ( ).split ( '   ' ) [1].strip ( ).split ( ':' ) [1]
                actors = re.sub ( r"[%s]+" % punc, "", actors.strip ( ) )#存在特殊字符需要先去除
                if len ( actors.split ( '/' ) ) == 1 :
                    actor = actors
                    if actor not in list_item:
                        graph.run (
                            "CREATE (actor:Person {name:'" + actor + "'})" )
                        list_item.append ( actor )
                    graph.run (
                            "match (p:Person{name:'" + actor + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (p)-[:acted_in]->(b)" )
                else :
                    actor = actors.split ( '/' )
                    if '...' in actor:
                        actor.remove ( '...' )
                    for i in range(len(actor)-1):
                        if actor[i] not in list_item :
                            graph.run (
                                "CREATE (actor:Person {name:'" + actor [i] + "'})" )
                            list_item.append ( actor [i] )
                        graph.run (
                                "match (p:Person{name:'" + actor[i] + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (p)-[:acted_in]->(b)" )
                #get time
                time=text1.strip ( ).split ( '/' ) [0].strip()
                if time not in list_item:
                    graph.run (
                        "CREATE (time:Time {year:'" + time + "'})" )
                    list_item.append ( time )
                graph.run (
                        "match (p:Time{year:'" + time + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (b)-[:created_in]->(p)" )
                #get country
                #maybe more than one
                country=text1.strip ( ).split ( '/' ) [1].strip().split(' ')[0]
                if country not in list_item:
                    graph.run (
                        "CREATE (country:Country {name:'" + country + "'})" )
                    list_item.append ( country )
                graph.run (
                        "match (p:Country {name:'" + country + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (b)-[:produced_by]->(p)" )
                #get type
                types=text1.strip ( ).split ( '/' ) [2].strip().split(' ')
                if len(types)==1:
                    type = types
                    if type not in list_item:
                        graph.run (
                            "CREATE (type:Type {name:'" + type + "'})" )
                        list_item.append ( type )
                    graph.run (
                            "match (p:Type{name:'" + type + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (b)-[:belong_to]->(p)" )
                else:
                    for i in range(0,len(types)):
                        if types[i] not in list_item:
                            graph.run (
                                "CREATE (type:Type {name:'" + types[i] + "'})" )
                            list_item.append ( types[i] )
                        type_relation="match (p:Type{name:'" + types[i] + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (b)-[:belong_to]->(p)"
                        graph.run (
                            "match (p:Type{name:'" + types[i] + "'}),(b:Movie{name:'" + film + "'})" + "CREATE (b)-[:belong_to]->(p)" )
            except:
                continue

代码比较粗糙,后续再完善。

3、知识图谱show

整体效果如上图,即可以通过country、type、time信息显性化的检索相关信息,如果只将movie、director、actor作为node,则需要点击具体节点才能看到其属性country、type、time等信息。

如此,一个简易的豆瓣top250知识图谱就构建好了,但是,此处仍存在一个问题-数据重复,做完后发现不仅仅是节点有重复,关系竟然也有重复的,这个问题还在探究中。

 

参考资源链接:[医疗知识图谱问答系统的设计与实现](https://wenku.csdn.net/doc/69bpzino24?utm_source=wenku_answer2doc_content) 为了在医疗知识图谱问答系统中有效构建和高效查询知识图谱,我们首先需要了解Neo4j的特点和操作。Neo4j是一个图数据库,它专门针对处理大量的关系型数据设计,非常适合用于知识图谱的存储和检索。以下是构建和查询知识图谱的详细步骤: 一、知识图谱构建 1. 数据准备:首先,通过Python进行数据爬取和预处理,从医疗知识源中提取出关键信息和实体关系。 2. 实体识别:利用自然语言处理技术,从文本中识别出医疗领域的实体,如疾病、药物、症状等。 3. 关系映射:将实体间的关系映射为图数据库中的节点和边。 4. 图构建:使用Cypher查询语言,将实体和关系导入Neo4j数据库中,构建知识图谱的节点和边。 二、知识图谱查询 1. 知识检索:当用户提出查询请求时,同样使用NLP技术分析其意图,并将其转换为图数据库能理解的查询语句。 2. Cypher查询:利用Cypher语言在Neo4j数据库中进行复杂的图查询,快速找到相关实体和它们之间的关系。 3. 结果提取:根据查询结果提取信息,进行排序、过滤等操作,最终返回给用户一个准确的答案。 4. 性能优化:对知识图谱查询进行性能分析和优化,确保系统的响应速度满足实时问答的需求。 结合以上步骤,我们可以利用PythonNeo4j的强大功能,在医疗知识图谱问答系统中实现知识图谱构建和高效查询。为了进一步掌握相关技术,建议阅读《医疗知识图谱问答系统的设计与实现》,该资料详细介绍了如何使用Python和相关技术来实现一个功能完善的问答系统,其中包含了对Neo4j的深入应用和数据处理的实用技巧,帮助你更有效地构建和维护知识图谱。 参考资源链接:[医疗知识图谱问答系统的设计与实现](https://wenku.csdn.net/doc/69bpzino24?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SeasonRun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值