首先需要下载gexf包,但是这个包比较古老,如果不换源的话直接conda或者pip安装是行不通的的,因此执行下面这个命令安装pygexf
pip install pygexf -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
执行了这步,在python模式下输入
import gexf
像我这样没有报错就是对的,然而只要你用的是python3肯定会报错,所以需要做一些改动
- 打开python下site-packages 文件夹,找到gexf文件夹,对文件夹内的程序进行修改。
- 我去原作者github逛了一圈,发现有对应python3的更新程序,因此把__init__.py和_gexf.py改一下就ok了。下图是在我电脑里两个程序的位置。你要是用的ananconda搭建的深度学习环境照猫画虎应该能找到,其他情况我就不赘述了,可以参考这个.
- 把__init__.py改为:
from ._gexf import Gexf
from ._gexf import Node
from ._gexf import Edge
from ._gexf import Graph
from ._gexf import GexfImport
- _gexf.py改为:
# -*- coding: utf-8 -*-
#
# Gexf library in python
# see gephi.org and gexf.net
#
# repository : http://github.com/paulgirard/pygexf
# documentation : http://packages.python.org/pygexf
#
# main developper : Paul Girard, médialab Sciences Po
# licence : GPL v3
#
from lxml import etree
from datetime import date
import itertools
import traceback
# missing features :
# data validation regarding attribute types
# phylogeny
# evolution ideas :
# add display stats on graph composition when exportingto xml
# add anti-paralell edges test
def msg_unexpected_tag(expected, got):
print("Error : incorrect xml. Expected tag {expected}, not {got}.".format(expected=expected, got=got))
def ns_clean(token):
i = token.find('}')
return token[i + 1:]
class Gexf:
def __init__(self, creator, description):
self.creator = creator
self.description = description
self.graphs = []
self.xmlns = "http://www.gephi.org/gexf/1.2draft"
self.xsi = "http://www.w3.org/2001/XMLSchema-instance"
self.schemaLocation = "http://www.gephi.org/gexf/1.1draft http://gephi.org/gexf/1.2draft.xsd"
self.viz = "http://www.gexf.net/1.2draft/viz"
self.version = "1.2"
def addGraph(self, type, mode, label, timeformat=""):
g = Graph(type, mode, label, timeformat)
self.graphs.append(g)
return g
def getXML(self):
gexfXML = etree.Element("{" + self.xmlns + "}gexf", version=self.version, nsmap={None: self.xmlns, 'viz': self.viz, 'xsi': self.xsi})
# gexfXML.set("xmlnsxsi",)
gexfXML.set("{xsi}schemaLocation", self.schemaLocation)
meta = etree.SubElement(gexfXML, "meta")
meta.set("lastmodified", date.today().isoformat())
etree.SubElement(meta, "creator").text = self.creator
etree.SubElement(meta, "description").text = self.description
for graph in self.graphs:
gexfXML.append(graph.getXML())
return gexfXML
def write(self, file, print_stat=True):
file.write(etree.tostring(self.getXML(), pretty_print=True, encoding='utf-8', xml_declaration=True))
if print_stat is True:
self.print_stat()
def print_stat(self):
for graph in self.graphs:
graph.print_stat()
@staticmethod
def importXML(gexf_file):
""" import gexf xml meta tags to create a Gexf Object and delegate Graph extraction to Graph class"""
# parse the gexf file
parser = etree.XMLParser(ns_clean=True)
tree = etree.parse((gexf_file), parser)
# start create Gexf Object
gexf_xml = tree.getroot()
tag = ns_clean(gexf_xml.tag).lower()
if tag != "gexf":
msg_unexpected_tag("gexf", tag)
return
gexf_obj = None
for child in gexf_xml:
tag = ns_clean(child.tag).lower()
# create a gexf object by importing meta tag
if tag == "meta":
meta_xml = child
for child in meta_xml:
tag = ns_clean(child.tag).lower()
if tag == "creator":
creator = child.text
if tag == "description":
description = child.text
gexf_obj = Gexf(creator=creator, description=description)
# export graph xml through Graph Class
if tag == "graph":
graph_xml = child
if gexf_obj is None:
msg_unexpected_tag("meta", tag)
return
Graph.importXML(graph_xml, gexf_obj)
return gexf_obj
class Graph:
def __init__(self, type, mode, label, time_format="double", start="", end=""):
# control variable
self.authorizedType = ("directed", "undirected")
self.authorizedMode = ("dynamic", "static")
# time format
# Discrete: integer or double
# Continuous : date (yyyy-mm-dd) or dateTime
# default : double
self.authorizedTimeFormat = ("integer", "double", "date", "dateTime")
self.defaultTimeFormat = "double"
self.defaultType = "directed"
self.defaultMode = "static"
self.label = label
if type in self.authorizedType:
self.type = type
else:
self.type = self.defaultType
if mode in self.authorizedMode:
self.mode = mode
else:
self.mode = self.defaultMode
if time_format in self.authorizedTimeFormat:
self.time_format = time_format
else:
self.time_format = self.defaultTimeFormat
self.start = start
self.end = end
self._attributes = Attributes()
self.attributes = self._attributes
self._nodes = {}
self.nodes = self._nodes
self._edges = {}
self.edges = self._edges
def addNode(self, id, label, start="", end="", startopen=False, endopen=False, pid="", r="", g="", b="", spells=[]):
self._nodes[str(id)] = Node(self, id, label, start, end, pid, r, g, b, spells, startopen, endopen)
return self._nodes[str(id)]
def nodeExists(self, id):
if id in self._nodes.keys():
return 1
else:
return 0
def addEdge(self, id, source, target, weight="", start="", end="", label="", r="", g="", b="", spells=[], startopen=False, endopen=False):
self._edges[str(id)] = Edge(self, id, source, target, weight, start, end, label, r, g, b, spells, startopen, endopen)
return self._edges[str(id)]
def addNodeAttribute(self, title, defaultValue=None, type="integer", mode="static", force_id=""):
# add to NodeAttributes
return self._attributes.declareAttribute("node", type, defaultValue, title, mode, force_id)
def addDefaultAttributesToNode(self, node):
""" deprecated """
pass
def checkNodeAttribute(self, id, value, start, end):
"""deprecated"""
pass
# check conformity with type is missing
# if id in self._nodesAttributes.keys() :
# if self._nodesAttributes[id]["mode"]=="static" and ( not start=="" or not end=="") :
# raise Exception("attribute "+str(id)+" is static you can't specify start or end dates. Declare Attribute as dynamic")
# return 1
# else :
# raise Exception("attribute id unknown. Add Attribute to graph first")
def addEdgeAttribute(self, title, defaultValue, type="integer", mode="static", force_id=""):
return self._attributes.declareAttribute("edge", type, defaultValue, title, mode, force_id)
def addDefaultAttributesToEdge(self, edge):
""" deprecated """
pass
def checkEdgeAttribute(self, id, value, start, end):
"""deprecated """
pass
# # check conformity with type is missing
# if id in self._edgesAttributes.keys() :
# if self._edgesAttributes[id]["mode"]=="static" and ( not start=="" or not end=="") :
# raise Exception("attribute "+str(id)+" is static you can't specify start or end dates. Declare Attribute as dynamic")
# return 1
# else :
# raise Exception("attribute id unknown. Add Attribute to graph first")
def getXML(self):
# return lxml etree element
graphXML = etree.Element("graph", defaultedgetype=self.type, mode=self.mode, label=self.label, timeformat=self.time_format)
for attributesElement in self.attributes.getAttributesDeclarationXML():
graphXML.append(attributesElement)
nodesXML = etree.SubElement(graphXML, "nodes")
node_ids = list(self._nodes.keys())
node_ids.sort()
for id in node_ids:
nodesXML.append(self._nodes[id].getXML())
edgesXML = etree.SubElement(graphXML, "edges")
edge_ids = list(self._edges.keys())
edge_ids.sort()
for id in edge_ids:
edgesXML.append(self._edges[id].getXML())
return graphXML
@staticmethod
def importXML(graph_xml, gexf_obj):
""" import graph xml tag to create a Graph Object and delegate Node/Edges extraction to Edge/Node class"""
# get Graph attributes
type = ""
mode = ""
label = ""
timeformat = "double"
for attr in graph_xml.attrib:
attr = attr.lower()
if attr == "defaultedgetype":
type = graph_xml.attrib[attr]
if attr == "mode":
mode = graph_xml.attrib[attr]
if attr == "label":
label = graph_xml.attrib[attr]
if attr == "timeformat":
timeformat = graph_xml.attrib[attr]
# create and attache the graph object to the Gexf object
graph_obj = gexf_obj.addGraph(type=type, mode=mode, label=label, timeformat=timeformat)
for child in graph_xml:
tag = ns_clean(child.tag).lower()
if tag == "attributes":
attributes_xml = child
# Delegate Attributes declaration to the attribute object
graph_obj.attributes.importAttributesXML(attributes_xml)
if tag == "nodes":
nodes_xml = child
# Delegate nodes creation to the Node class
Node.importXML(nodes_xml, graph_obj)
if tag == "edges":
edges_xml = child
# Delegate edges creation to the Edge class
Edge.importXML(edges_xml, graph_obj)
def print_stat(self):
print(self.label + " " + self.type + " " + self.mode + " " + self.start + " " + self.end)
print("number of nodes : " + str(len(self._nodes)))
print("number of edges : " + str(len(self._edges)))
class Attributes(dict):
"""
attributes=
{
"node" :
{ "id1" : {"id":"id1","title":"age","type":"integer","defaultValue":50,"mode":"static"}, },
"edge" :
{ "id2" : {"id":"id2","title":"relationship","type":"string","defaultValue":"friend",mode:"dynamic"}, },
}
"""
def __init__(self):
self.type_choices = ["integer", "string", "float", "double", "boolean", "date", "URI"]
self.attClass_choices = ["node", "edge"]
self.mode_choices = ["static", "dynamic"]
for attClass in self.attClass_choices:
self[attClass] = {}
def declareAttribute(self, attClass, type, defaultValue, title="", mode="static", id=None):
"""
add a new attribute declaration to the graph
"""
if attClass in self.attClass_choices:
# should add quality control here on type and defaultValue
# if no id given generating a numerical one based on dict length
if not id:
id = str(len(self[attClass]))
self[attClass][id] = {"id": id, "type": type, "defaultValue": defaultValue, "mode": mode, "title": title}
return id
else:
raise Exception("wrong attClass : " + str(attClass) + " Should be in " + str(type_choices))
def makeAttributeInstance(self, attClass, id=None, value=None, start=None, end=None, startopen=False, endopen=False):
"""
generate an attribute to be include to a node or edge.
copied from the declared attributes, thus any attribute has to be declared first
"""
if attClass in self.attClass_choices:
if id in self[attClass].keys():
att = {"id": id}
att["value"] = value if value else self[attClass][id]["defaultValue"]
if self[attClass][id]["mode"] == "dynamic" and start or end:
# start & end will be discarded if the mode is set to static
if start:
att["start"] = start
if startopen:
att["startopen"] = startopen
if end:
att["end"] = end
if endopen:
att["endopen"] = endopen
return att
else:
raise Exception("wrong attribute id (%s), declare the attribute first with declareAttribute" % (id, ))
else:
raise Exception("wrong attClass : " + str(attClass) + " Should be in " + str(self.type_choices))
def getAttributesDeclarationXML(self):
""" generate attributes declaration XML """
# return lxml etree element
allAttributesXML = []
if len(self) > 0:
# iter on node and then edge atts
for attClass, atts in self.items():
# group by mode
key_mode = lambda att: att["mode"]
atts_sorted_by_mode = sorted(list(atts.values()), key=key_mode, reverse=True)
for mode, atts in itertools.groupby(atts_sorted_by_mode, key_mode):
# generate on attributes by mode
attributesXML = etree.Element("attributes")
attributesXML.set("class", attClass)
attributesXML.set("mode", mode)
# generate attribute by id order
for att in sorted(atts, key=lambda att: att["id"]):
attributeXML = etree.SubElement(attributesXML, "attribute")
attributeXML.set("id", str(att["id"]))
attributeXML.set("title", att["title"])
attributeXML.set("type", att["type"])
if att["defaultValue"]:
etree.SubElement(attributeXML, "default").text = att["defaultValue"]
allAttributesXML.append(attributesXML)
return allAttributesXML
@staticmethod
def getAttributesXML(atts):
""" get XML attValues for an element (Node or Edge) by passing an attribute values list (stored in Nodes and Edges)"""
if len(atts) > 0:
attValuesXML = etree.Element("attvalues")
for att in atts:
attValueXML = etree.SubElement(attValuesXML, "attvalue")
attValueXML.set("for", str(att["id"]))
attValueXML.set("value", att["value"])
if "start" in att.keys() and not att["start"] == "":
attValueXML.set("start" if not "startopen" in att.keys() or not att["startopen"] else "startopen", att["start"])
if "end" in att.keys() and not att["end"] == "":
attValueXML.set("end" if not "endopen" in att.keys() or not att["endopen"] else "endopen", att["end"])
return attValuesXML
else:
return None
def importAttributesXML(self, attributes_xml):
""" get XML attributes declaration of a graph gexf"""
attr_class = None
mode = ""
for attr in attributes_xml.attrib:
attr = attr.lower()
if attr == "class":
attr_class = attributes_xml.attrib[attr].lower()
if attr == "mode":
mode = attributes_xml.attrib[attr]
for child in attributes_xml:
tag = ns_clean(child.tag).lower()
if tag == "attribute":
attribute_xml = child
id = ""
title = ""
type = ""
for attr in attribute_xml.attrib:
attr = attr.lower()
if attr == "id":
id = attribute_xml.attrib[attr]
if attr == "title":
title = attribute_xml.attrib[attr]
if attr == "type":
type = attribute_xml.attrib[attr]
default = ""
for child in attribute_xml:
tag = ns_clean(child.tag).lower()
if tag == "default":
default = child.text
self.declareAttribute(attr_class, type, default, title, mode, id)
def importAttributesValuesXML(self, attClass, attvalues_xml):
""" import attributes values from attvalues gexf xml tag attached to nodes or edges"""
atts = []
for attvalues in attvalues_xml:
for child in attvalues:
tag = ns_clean(child.tag).lower()
if tag == "attvalue":
attvalue_xml = child
id = ""
value = ""
start = ""
startopen = False
end = ""
endopen = False
for attr in attvalue_xml.attrib:
if attr == "for":
id = attvalue_xml.attrib[attr]
if attr == "value":
value = attvalue_xml.attrib[attr]
if attr == "start":
start = attvalue_xml.attrib[attr]
if attr == "end":
end = attvalue_xml.attrib[attr]
if attr == "startopen":
start = attvalue_xml.attrib[attr]
startopen = True
if attr == "endopen":
end = attvalue_xml.attrib[attr]
endopen = True
atts.append(self.makeAttributeInstance(attClass, id, value, start, end, startopen, endopen))
return atts
class Spells(list):
'''
spells are time periods
spells is a list of dictionaries
a spell is a dict : {"start":"YYYY-MM-DD","end":"YYYY-MM-DD"}
'''
def getXML(self):
spellsXML = etree.Element("spells")
for spell in self:
spellXML = etree.SubElement(spellsXML, "spell")
if "start" in spell.keys():
spellXML.set("start", spell["start"])
if "end" in spell.keys():
spellXML.set("end", spell["end"])
return spellsXML
@staticmethod
def importXML(spellsxmltree):
return Spells([spell.attrib for spell in spellsxmltree])
class Node:
def __init__(self, graph, id, label, start="", end="", pid="", r="", g="", b="", spells=[], startopen=False, endopen=False):
self.id = id
self.label = label
self.start = start
self.startopen = startopen
self.end = end
self.endopen = endopen
self.pid = pid
self._graph = graph
self.setColor(r, g, b)
#spells expecting format = [{start:"",end:""},...]
self.spells = spells
if not self.pid == "":
if not self._graph.nodeExists(self.pid):
raise Exception("pid " + self.pid + " node unknown, add nodes to graph first")
self._attributes = []
self.attributes = self._attributes
# add existing nodesattributes default values : bad idea and unecessary
#self._graph.addDefaultAttributesToNode(self)
def addAttribute(self, id, value, start="", end="", startopen=False, endopen=False):
self._attributes.append(self._graph.attributes.makeAttributeInstance("node", id, value, start, end, startopen, endopen))
def getXML(self):
# return lxml etree element
try:
nodeXML = etree.Element("node", id=str(self.id), label=self.label)
if not self.start == "":
nodeXML.set("start" if not self.startopen else "startopen", self.start)
if not self.end == "":
nodeXML.set("end" if not self.endopen else "endopen", self.end)
if not self.pid == "":
nodeXML.set("pid", self.pid)
# attributes
if self._attributes:
nodeXML.append(Attributes.getAttributesXML(self._attributes))
# spells
if self.spells:
print("found spells in node " + self.id)
nodeXML.append(self.spells.getXML())
if not self.r == "" and not self.g == "" and not self.b == "":
#color : <viz:color r="239" g="173" b="66"/>
colorXML = etree.SubElement(nodeXML, "{http://www.gexf.net/1.1draft/viz}color")
colorXML.set("r", self.r)
colorXML.set("g", self.g)
colorXML.set("b", self.b)
return nodeXML
except Exception as e:
print(self.label)
print(self._attributes)
print(e)
traceback.print_exc()
exit()
def getAttributes(self):
attsFull = []
for att in self._attributes:
attFull = self._graph.attributes["node"][att["id"]].copy()
attFull.update(att)
attsFull.append(attFull)
return attsFull
@staticmethod
def importXML(nodes_xml, graph_obj):
for child in nodes_xml:
tag = ns_clean(child.tag).lower()
if tag == "node":
node_xml = child
id = ""
label = ""
start = ""
startopen = False
end = ""
endopen = False
pid = ""
r = ""
g = ""
b = ""
for attr in node_xml.attrib:
attr = attr.lower()
if attr == "id":
id = node_xml.attrib[attr]
if attr == "label":
label = node_xml.attrib[attr]
if attr == "start":
start = node_xml.attrib[attr]
if attr == "end":
start = node_xml.attrib[attr]
if attr == "startopen":
start = attvalue_xml.attrib[attr]
startopen = True
if attr == "endopen":
end = attvalue_xml.attrib[attr]
endopen = True
if attr == "pid":
pid = node_xml.attrib[attr]
attvalues_xml = []
spells = []
for child in node_xml:
tag = ns_clean(child.tag).lower()
if tag == "attvalues":
attvalues_xml.append(child)
if tag == "viz:color":
r = child.attrib["r"]
g = child.attrib["g"]
b = child.attrib["b"]
if tag == "spells":
spells = Spells.importXML(child)
node_obj = graph_obj.addNode(id=id, label=label, start=start, end=end, startopen=startopen, endopen=endopen, pid=pid, r=r, g=g, b=b, spells=spells)
node_obj._attributes = graph_obj.attributes.importAttributesValuesXML("node", attvalues_xml)
def setColor(self, r, g, b):
self.r = r
self.g = g
self.b = b
def __str__(self):
return self.label
class Edge:
def __init__(self, graph, id, source, target, weight="", start="", end="", label="", r="", g="", b="", spells=[], startopen=False, endopen=False):
self.id = id
self._graph = graph
if self._graph.nodeExists(source):
self._source = source
self.source = self._source
else:
raise Exception("source " + source + " node unknown, add nodes to graph first")
if self._graph.nodeExists(target):
self._target = target
self.target = self._target
else:
raise Exception("target " + target + " node unknown, add nodes to graph first")
self.start = start
self.startopen = startopen
self.end = end
self.endopen = endopen
self.weight = weight
self.label = label
self._attributes = []
self.attributes = self._attributes
# COLOR on edges now supported in GEXF 1.2
self.setColor(r, g, b)
#spells expecting format = [{start:"",end:""},...]
self.spells = Spells(spells)
# add existing nodesattributes default values : bad idea and unecessary
#self._graph.addDefaultAttributesToEdge(self)
def addAttribute(self, id, value, start="", end="", startopen=False, endopen=False):
self._attributes.append(self._graph.attributes.makeAttributeInstance("edge", id, value, start, end, startopen, endopen))
def getXML(self):
# return lxml etree element
try:
edgeXML = etree.Element("edge", id=str(self.id), source=str(self._source), target=str(self._target))
if not self.start == "":
edgeXML.set("start" if not self.startopen else "startopen", self.start)
if not self.end == "":
edgeXML.set("end" if not self.endopen else "endopen", self.end)
if not self.weight == "":
edgeXML.set("weight", str(self.weight))
if not self.label == "":
edgeXML.set("label", self.label)
# attributes
if self._attributes:
edgeXML.append(Attributes.getAttributesXML(self._attributes))
# spells
if self.spells:
#spellsXML = etree.SubElement(edgeXML, "spells")
#spellsXML.append(self.spells.getXML())
edgeXML.append(self.spells.getXML())
# COLOR on edges is supported in GEXF since 1.2
if not self.r == "" and not self.g == "" and not self.b == "":
#color : <viz:color r="239" g="173" b="66"/>
colorXML = etree.SubElement(edgeXML, "{http://www.gexf.net/1.2draft/viz}color")
colorXML.set("r", self.r)
colorXML.set("g", self.g)
colorXML.set("b", self.b)
return edgeXML
except Exception as e:
print(self._source + " " + self._target)
print(e)
exit()
def getAttributes(self):
attsFull = []
for att in self._attributes:
attFull = self._graph.attributes["edge"][att["id"]].copy()
attFull.update(att)
attsFull.append(attFull)
return attsFull
@staticmethod
def importXML(edges_xml, graph_obj):
for child in edges_xml:
tag = ns_clean(child.tag).lower()
if tag == "edge":
edge_xml = child
id = ""
source = ""
target = ""
weight = ""
start = ""
startopen = False
end = ""
endopen = False
label = ""
r = ""
g = ""
b = ""
for attr in edge_xml.attrib:
attr = attr.lower()
if attr == "id":
id = edge_xml.attrib[attr]
if attr == "source":
source = edge_xml.attrib[attr]
if attr == "target":
target = edge_xml.attrib[attr]
if attr == "weight":
weight = edge_xml.attrib[attr]
if attr == "start":
start = edge_xml.attrib[attr]
if attr == "end":
end = edge_xml.attrib[attr]
if attr == "startopen":
start = edge_xml.attrib[attr]
startopen = True
if attr == "endopen":
end = edge_xml.attrib[attr]
endopen = True
if attr == "label":
label = edge_xml.attrib[attr]
spells = []
attvalues_xml = []
for child in edge_xml:
tag = ns_clean(child.tag).lower()
if tag == "attvalues":
attvalues_xml.append(child)
if tag == "spells":
spells = Spells.importXML(child)
if tag == "viz:color":
r = child.attrib["r"]
g = child.attrib["g"]
b = child.attrib["b"]
edge_obj = graph_obj.addEdge(id=id, source=source, target=target, weight=weight, start=start, end=end, startopen=startopen, endopen=endopen, label=label, r=r, g=g, b=b, spells=spells)
edge_obj._attributes = graph_obj.attributes.importAttributesValuesXML("edge", attvalues_xml)
# COLOR on edges is supported in GEXF since 1.2
def setColor(self, r, g, b):
self.r = r
self.g = g
self.b = b
class GexfImport:
# class coded by elie Rotenberg, médialab 20/07/2010
# deprecated : import XML codes are now included to the Gexf, Graph, Attribute, Node, Edge classes
def __init__(self, file_like):
parser = etree.XMLParser(ns_clean=True)
tree = etree.parse(file_like, parser)
gexf_xml = tree.getroot()
tag = self.ns_clean(gexf_xml.tag).lower()
if tag != "gexf":
self.msg_unexpected_tag("gexf", tag)
return
self.gexf_obj = None
for child in gexf_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "meta":
meta_xml = child
self.gexf_obj = self.extract_gexf_obj(meta_xml)
if tag == "graph":
graph_xml = child
if self.gexf_obj == None:
self.msg_unexpected_tag("meta", tag)
return
self.graph_obj = self.extract_graph_obj(graph_xml)
def ns_clean(self, token):
i = token.find('}')
return token[i + 1:]
def msg_unexpected_tag(self, expected, got):
print("Error : incorrect xml. Expected tag {expected}, not {got}.".format(expected=expected, got=got))
def extract_gexf_obj(self, meta_xml):
for child in meta_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "creator":
creator = child.text
if tag == "description":
description = child.text
return Gexf(creator=creator, description=description)
def extract_graph_obj(self, graph_xml):
type = ""
mode = ""
label = ""
timeformat = "double"
for attr in graph_xml.attrib:
attr = attr.lower()
if attr == "defaultedgetype":
type = graph_xml.attrib[attr]
if attr == "mode":
mode = graph_xml.attrib[attr]
if attr == "label":
label = graph_xml.attrib[attr]
if attr == "timeformat":
timeformat = graph_xml.attrib[attr]
self.graph_obj = self.gexf_obj.addGraph(type=type, mode=mode, label=label, timeformat=timeformat)
for child in graph_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "attributes":
attributes_xml = child
self.extract_attributes(attributes_xml)
if tag == "nodes":
nodes_xml = child
self.extract_nodes(nodes_xml)
if tag == "edges":
edges_xml = child
self.extract_edges(edges_xml)
def extract_attributes(self, attributes_xml):
attr_class = None
mode = ""
for attr in attributes_xml.attrib:
attr = attr.lower()
if attr == "class":
attr_class = attributes_xml.attrib[attr].lower()
if attr == "mode":
mode = attributes_xml.attrib[attr]
for child in attributes_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "attribute":
attribute_xml = child
self.extract_attribute(attribute_xml, attr_class, mode)
def extract_attribute(self, attribute_xml, attr_class, mode):
id = ""
title = ""
type = ""
for attr in attribute_xml.attrib:
attr = attr.lower()
if attr == "id":
id = attribute_xml.attrib[attr]
if attr == "title":
title = attribute_xml.attrib[attr]
if attr == "type":
type = attribute_xml.attrib[attr]
default = ""
for child in attribute_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "default":
default = child.text
if attr_class == "node":
self.graph_obj.addNodeAttribute(title, default, type, mode, force_id=id)
if attr_class == "edge":
self.graph_obj.addEdgeAttribute(title, default, type, mode, force_id=id)
def extract_nodes(self, nodes_xml):
for child in nodes_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "node":
node_xml = child
self.extract_node(node_xml)
def extract_node(self, node_xml):
id = ""
label = ""
start = ""
startopen = False
end = ""
endopen = False
pid = ""
r = ""
g = ""
b = ""
for attr in node_xml.attrib:
attr = attr.lower()
if attr == "id":
id = node_xml.attrib[attr]
if attr == "label":
label = node_xml.attrib[attr]
if attr == "start":
start = node_xml.attrib[attr]
if attr == "end":
start = node_xml.attrib[attr]
if attr == "startopen":
start = attvalue_xml.attrib[attr]
startopen = True
if attr == "endopen":
end = attvalue_xml.attrib[attr]
endopen = True
if attr == "pid":
pid = node_xml.attrib[attr]
attvalues_xmls = []
spells = []
for child in node_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "attvalues":
attvalues_xmls.append(child)
if tag == "viz:color":
r = child.attrib["r"]
g = child.attrib["g"]
b = child.attrib["b"]
if tag == "spells":
spells = [spell.attrib for spell in child]
self.node_obj = self.graph_obj.addNode(id=id, label=label, start=start, end=end, startopen=startopen, endopen=endopen, pid=pid, r=r, g=g, b=b, spells=spells)
for attvalues_xml in attvalues_xmls:
self.extract_node_attvalues(attvalues_xml)
def extract_node_attvalues(self, attvalues_xml):
for child in attvalues_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "attvalue":
attvalue_xml = child
self.extract_node_attvalue(attvalue_xml)
def extract_node_attvalue(self, attvalue_xml):
id = ""
value = ""
start = ""
startopen = False
end = ""
endopen = False
for attr in attvalue_xml.attrib:
attr = attr.lower()
if attr == "for":
id = attvalue_xml.attrib[attr]
if attr == "value":
value = attvalue_xml.attrib[attr]
if attr == "start":
start = attvalue_xml.attrib[attr]
if attr == "end":
end = attvalue_xml.attrib[attr]
if attr == "startopen":
start = attvalue_xml.attrib[attr]
startopen = True
if attr == "endopen":
end = attvalue_xml.attrib[attr]
endopen = True
self.node_obj.addAttribute(id=id, value=value, start=start, end=end, startopen=startopen, endopen=endopen)
def extract_edges(self, edges_xml):
for child in edges_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "edge":
edge_xml = child
self.extract_edge(edge_xml)
def extract_edge(self, edge_xml):
id = ""
source = ""
target = ""
weight = ""
start = ""
startopen = False
end = ""
endopen = False
label = ""
r = ""
g = ""
b = ""
for attr in edge_xml.attrib:
attr = attr.lower()
if attr == "id":
id = edge_xml.attrib[attr]
if attr == "source":
source = edge_xml.attrib[attr]
if attr == "target":
target = edge_xml.attrib[attr]
if attr == "weight":
weight = edge_xml.attrib[attr]
if attr == "start":
start = edge_xml.attrib[attr]
if attr == "end":
end = edge_xml.attrib[attr]
if attr == "startopen":
start = edge_xml.attrib[attr]
startopen = True
if attr == "endopen":
end = edge_xml.attrib[attr]
endopen = True
if attr == "label":
label = edge_xml.attrib[attr]
spells = []
attvalues_xml = []
for child in edge_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "attvalues":
attvalues_xml = child
if tag == "spells":
spells = [spell.attrib for spell in child]
if tag == "viz:color":
r = child.attrib["r"]
g = child.attrib["g"]
b = child.attrib["b"]
self.edge_obj = self.graph_obj.addEdge(id=id, source=source, target=target, weight=weight, start=start, end=end, startopen=startopen, endopen=endopen, label=label, r=r, g=g, b=b, spells=spells)
self.extract_edge_attvalues(attvalues_xml)
def extract_edge_attvalues(self, attvalues_xml):
for child in attvalues_xml:
tag = self.ns_clean(child.tag).lower()
if tag == "attvalue":
attvalue_xml = child
self.extract_edge_attvalue(attvalue_xml)
# def addAttribute(self,id,value,start="",end="") :
def extract_edge_attvalue(self, attvalue_xml):
id = ""
value = ""
start = ""
startopen = True
end = ""
endopen = True
for attr in attvalue_xml.attrib:
if attr == "for":
id = attvalue_xml.attrib[attr]
if attr == "value":
value = attvalue_xml.attrib[attr]
if attr == "start":
start = attvalue_xml.attrib[attr]
if attr == "end":
end = attvalue_xml.attrib[attr]
if attr == "startopen":
startopen = attvalue_xml.attrib[attr]
if attr == "endopen":
endopen = attvalue_xml.attrib[attr]
self.edge_obj.addAttribute(id=id, value=value, start=start, end=end, startopen=startopen, endopen=endopen)
def gexf(self):
return self.gexf_obj
然后再次import gexf,此时应该是没有问题的。之后用程序测试一下:
- 关于测试程序,这里要多说几句,下面的测试程序代码片倒数第三行
output_file=open("./data.gexf","wb")
的形式具体取决于 - 你是windows还是linux
- 你是python2还是python3
1.在python3且linux情况下,直接执行下面的大段代码
2.在python3且windows情况下,则需把倒数第三行改为
output_file=open(".\data.gexf","wb")
3.我没用过python2,所以这些同学如果失败的话,先看看是不是1和2说的操作系统的问题。之后不行的话,可以试试把“wb”
改为“w“
(未测试过)
import sys,pprint
from gexf import Gexf
# test helloworld.gexf
gexf = Gexf("Gephi.org","A Web network")
graph=gexf.addGraph("directed","static","A Web network")
atr1 = graph.addNodeAttribute('url',type='string')
atr2 = graph.addNodeAttribute('indegree',type='float')
atr3 = graph.addNodeAttribute('frog',type='boolean',defaultValue='true')
tmp = graph.addNode("0","Gephi")
tmp.addAttribute(atr1,"http://gephi.org")
tmp.addAttribute(atr2,'1')
tmp = graph.addNode("1","Webatlas")
tmp.addAttribute(atr1,"http://webatlas.fr")
tmp.addAttribute(atr2,'2')
tmp = graph.addNode("2","RTGI")
tmp.addAttribute(atr1,"http://rtgi.fr")
tmp.addAttribute(atr2,'1')
tmp = graph.addNode("3","BarabasiLab")
tmp.addAttribute(atr1,"http://barabasilab.com")
tmp.addAttribute(atr2,'1')
tmp.addAttribute(atr3,'false')
graph.addEdge("0","0","1",weight='1')
graph.addEdge("1","0","2",weight='1')
graph.addEdge("2","1","0",weight='1')
graph.addEdge("3","2","1",weight='1')
graph.addEdge("4","0","3",weight='1')
output_file=open("./data.gexf","wb")
gexf.write(output_file)
output_file.close()
执行完后,在你代码文件的父目录下,应该会产生一个data.gexf文件,大功告成!
Reference:
- 这个博客比较优质,我在上面做了一点改进,不用手动在_gexf里面找空格,而且后面更新的python3版本的_gexf.py(1000多行)比原来python2(600多行)的要长很多。
2.Python生成gexf文件并导入gephi做网络图分析
- 测试程序来源