File size: 5,078 Bytes
3c15751
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""
Data Scientist.: Dr.Eddy Giusepe Chirinos Isidro
"""
"""Importando Bibliotecas:"""
import requests
from bs4 import BeautifulSoup
import spacy
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd

"""coleta e pré-processamento de dados (usamos a página da Wikipedia):"""
url = "https://pt.wikipedia.org/wiki/William_Shakespeare"

# Envie uma solicitação HTTP para o URL e recupere o conteúdo HTML:
response = requests.get(url)
# Analise o conteúdo HTML usando BeautifulSoup:
soup = BeautifulSoup(response.text, "html.parser")
# Extraia o conteúdo do texto de um elemento HTML específico com o id "mw-content-text":
text = soup.find("div", id="mw-content-text").text
# Substitua caracteres de nova linha por espaços e limite o texto aos primeiros 1.000 caracteres:
text = text.replace("\n", " ")
text = text[:1500]
print(text)

"""Usamos Reconhecimento de Entidade Nomeada (NER) - usamos um modelo pré-treinado para o português:"""
nlp = spacy.load("pt_core_news_lg")
# Processe o texto com o pipeline de NLP do spaCy:
doc = nlp(text)
# Inicialize listas vazias para armazenar entidades reconhecidas e seus rótulos:
entities = []
labels = []
# Extraia entidades nomeadas e seus rótulos:
for ent in doc.ents:
    entities.append(ent.text)
    labels.append(ent.label_)
print("\n")    
print('Entidades:', entities)
print("")
print('Labels:', labels)

"""Extraindo Relações entre Entidades:"""
# Inicialize uma lista vazia para armazenar relações:
relations = []

# Iterar através de frases no texto processado:
for sent in doc.sents:
    sent_doc = nlp(sent.text)
    subject = None
    object = None
    predicate = None
    
    # Iterar através de tokens na frase para identificar sujeito, objeto e predicado:
    for token in sent_doc:
        if token.dep_ == "nsubj":
            subject = token.text
        if token.dep_ == "pobj":
            object = token.text
        if token.dep_ == "ROOT":
            predicate = token.text
    
    # Se sujeito, objeto e predicado forem encontrados, armazene a relação:
    if subject and object and predicate:
        relation = (subject, predicate, object)
        relations.append(relation)
print('Relações:', relations)

"""Criando um DataFrame:"""
# Crie pares de entidades consecutivas:
entity_pairs = list(zip(entities, entities[1:]))

# Certifique-se de que as relações e os pares de entidades tenham o mesmo comprimento:
relations = relations[:len(entity_pairs)]
# Extraia a source e target de pares de entidades:
source = [i[0] for i in entity_pairs]
target = [i[1] for i in entity_pairs]
# Certifique-se de que as relações tenham o mesmo comprimento que a source e o target:
missing_relations = ["N/A"] * (len(entity_pairs) - len(relations))
relations += missing_relations
# Crie um DataFrame para representar o 'knowledge graph':
kg_df = pd.DataFrame({'source': source, 'target': target, 'edge': relations})
print(kg_df)

"""Construindo o Gráfico de Conhecimento:"""
# Crie um gráfico direcionado do DataFrame usando NetworkX:
G = nx.from_pandas_edgelist(kg_df, "source", "target", edge_attr=True, create_using=nx.MultiDiGraph())

"""Visualizando o Gráfico de Conhecimento:"""
# Calcule o comprimento máximo da palavra nos rótulos de cada nó:
max_word_lengths = [max(len(word) for word in node.split()) for node in G.nodes()]

# Calculate adaptive node sizes based on the maximum word length in each label
node_sizes = [max_word_length * 400 for max_word_length in max_word_lengths]
# Create a figure for the graph visualization
plt.figure(figsize=(12, 12))
fig = plt.figure(figsize=(12, 12))
# Define the layout for the graph using a spring layout with a seed for reproducibility
pos = nx.spring_layout(G, seed=42)
# Define the node colors for different types of entities
node_colors = []
for node in G.nodes():
    if node in ["William Shakespeare", "English", "Stratford-upon-Avon", "London", "England"]:
        node_colors.append("#ff7f0e")  # Laranja para localizações
    else:
        node_colors.append("#1f77b4")  # Blue for people
# Draw nodes and edges with improved aesthetics and adaptive node sizes
nx.draw(G, pos, node_color=node_colors, edge_color="#888888", node_size=node_sizes, font_size=10,
        font_color="white", font_weight="bold", alpha=0.9, linewidths=0.5, width=1.0, cmap=plt.cm.viridis)
# Create a dictionary to store node labels with line breaks for long labels
node_labels = {}
for node in G.nodes():
    label = node
    if len(node) > 2:  # Add line break for labels with more than two words
        label = '\n'.join(node.split())
    node_labels[node] = label
# Draw node labels with automatic placement and text wrapping
nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=10, font_color="white", font_weight="bold", alpha=0.9,
                        verticalalignment="center", horizontalalignment="center")
# Set the title for the graph
plt.title("William Shakespeare Knowledge Graph", fontsize=16)
fig.set_facecolor("#00000F")
# Turn off the axis
plt.axis('off')
# Display the knowledge graph
plt.show()