Fluxo de Trabalho Detalhado
1. Desenvolvimento Local no iMac
Instalar e configurar o ambiente de desenvolvimento no iMac.
# Instalar Python e Pip
python --version
pip --version
# Criar e ativar um ambiente virtual
python -m venv myenv
source myenv/bin/activate # No Windows use `myenv\Scripts\activate`
# Instalar as bibliotecas necessárias
pip install flask spacy networkx
python -m spacy download en_core_web_sm
2. Configuração do Backend
Crie o arquivo app.py com o seguinte conteúdo:
from flask import Flask, request, jsonify
import spacy
import networkx as nx
from networkx.readwrite import json_graph
app = Flask(__name__)
nlp = spacy.load('en_core_web_sm')
def text_to_graph(text):
doc = nlp(text);
G = nx.DiGraph();
for ent in doc.ents:
G.add_node(ent.text, label=ent.label_);
for sent in doc.sents:
for token in sent:
if token.dep_ in ('nsubj', 'dobj'):
G.add_edge(token.head.text, token.text, label=token.dep_);
return G;
@app.route('/update_graph', methods=['POST'])
def update_graph():
text = request.json.get('text');
G = text_to_graph(text);
graph_data = json_graph.node_link_data(G);
return jsonify(graph_data);
if __name__ == '__main__':
app.run(debug=True);
3. Executar o Backend Localmente
python app.py
4. Configuração do Frontend
Crie o arquivo index.html com o seguinte conteúdo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Grafo Interativo</title>
<style>
#graph {
width: 100%;
height: 600px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<h1>Grafo Interativo</h1>
<textarea id="input-text" rows="10" cols="50">Digite seu texto aqui...</textarea>
<button id="update-button">Atualizar Grafo</button>
<div id="graph"></div>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
document.getElementById('update-button').addEventListener('click', function() {
var text = document.getElementById('input-text').value;
fetch('/update_graph', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ text: text })
})
.then(response => response.json())
.then(data => {
updateGraph(data);
});
});
function updateGraph(data) {
var svg = d3.select("#graph").html("").append("svg")
.attr("width", "100%")
.attr("height", "100%")
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.append("g");
var width = document.getElementById('graph').clientWidth;
var height = document.getElementById('graph').clientHeight;
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) { return d.id; }).distance(150))
.force("charge", d3.forceManyBody().strength(-300))
.force("center", d3.forceCenter(width / 2, height / 2));
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(data.links)
.enter().append("line")
.attr("stroke-width", 2);
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("g")
.data(data.nodes)
.enter().append("g")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node.append("circle")
.attr("r", 10)
.attr("fill", "#69b3a2");
node.append("text")
.attr("x", 12)
.attr("dy", ".35em")
.text(function (d) { return d.id; });
simulation
.nodes(data.nodes)
.on("tick", ticked);
simulation.force("link")
.links(data.links);
function ticked() {
link
.attr("x1", function (d) { return d.source.x; })
.attr("y1", function (d) { return d.source.y; })
.attr("x2", function (d) { return d.target.x; })
.attr("y2", function (d) { return d.target.y; });
node
.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
}
</script>
</body>
</html>