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>