« SummarizingBot » : différence entre les versions
Aucun résumé des modifications |
Aucun résumé des modifications |
||
| Ligne 3 : | Ligne 3 : | ||
==Description== | ==Description== | ||
Le '''SummarizingBot''' crée un résumé, lisible, pour différents personnages sur la base des données saisies dans la partie Biographie | Le '''SummarizingBot''' crée un résumé, lisible, pour différents personnages sur la base des données saisies dans la partie Biographie de la page Wiki de chaque personnage (tous les personnages traités se trouvent dans la page Wiki [[Biographies]]). Le volume approximatif du résume est de 200 mots. La taille du résume dépend fortement des qualités des données d'origine, acquises de la page du personnage. C'est-à-dire, leur volume (au moins 15 entrées) et l'exactitude de l'entrée (syntaxes du Wiki doivent être respectés). | ||
Le principe clé du bot est | Le principe clé du bot est l'analyse des données (entrées) en utilisant le concept de '''Expression Régulière''' (Regular Expression ou RegExp) pour identifier les différentes parties d’entrée (une ligne de donnée). Grâce à cette analyse, on va obtenir des blocs d'information à partir de laquelle chaque entrée est consisté. Ces blocs sont les suivants : Le bloc du Data, Le bloc de la Ville et, finalement, Le bloc d’information sur l'évènement. Ensuite, on tire les informations supplémentaires de chaque bloc et on les traite avec de différentes fonctions. En ce moment-là, on va comprendre quel type de données on a dans le bloc. Si le bloc est de bonne structure on va continuer à le traiter, sinon on va éliminer ce bloc. On peut facilement appliquer les fonctions pour chaque cas particulier des données dans le bloc pour créer une structure correcte applicable au résume. | ||
La performance du code | La performance du code est telle qu'environ 92,8% de données du totale sont traitées et utilisées pour créer le résume. Ce pourcentage a été calculé comme le rapport entre le nombre total de lignes correctement lues par le code et le nombre total de lignes lues par le code de tous les pages de la Biographie. | ||
=== Expresion Régulière === | === Expresion Régulière === | ||
| Ligne 30 : | Ligne 30 : | ||
=== Datum Vérification === | === Datum Vérification === | ||
On veut fournir | On veut fournir quelques exemples du traitement des lignes de données. | ||
<pre> | <pre> | ||
[1993.05.23][][] ---> "False'', car on a une ligne vide par rapport l'information. | [1993.05.23][][] ---> "False'', car on a une ligne vide par rapport à l'information. | ||
</pre> | </pre> | ||
| Ligne 41 : | Ligne 41 : | ||
<pre> | <pre> | ||
[1993-1994][Milan][Information] ---> "False'', car on a une date qui ne respecte pas le RegExp pour | [1993-1994][Milan][Information] ---> "False'', car on a une date qui ne respecte pas le RegExp pour la date (format pas bon). | ||
</pre> | </pre> | ||
<pre> | <pre> | ||
[1993.05.23][Milan11][Information] ou [1993.05.23][Quelque part][Information] ---> "False'', car on a | [1993.05.23][Milan11][Information] ou [1993.05.23][Quelque part][Information] ---> "False'', car on a un lieu qui n'a pas un bon format (chiffres) ou il y a nombreux espaces dans le série. | ||
</pre> | </pre> | ||
==Points Critique des Performances== | ==Points Critique des Performances== | ||
Les points critiques sont les suivants : | |||
*Erreurs dans la saisie des données dans la biographie. Non-respect la syntaxe | *Erreurs dans la saisie des données dans la biographie. Non-respect de la syntaxe posée pour l'entrée dans la Biographie. | ||
* | *Problème de la langue utilisée. La langue française est rarement utilisée dans les réseaux de neurones artificiels (artificial neural network) qui peuvent créer du texte à partir de données qu'on a. | ||
*La grammaire française assez compliquée. | *La grammaire française est assez compliquée. Ceci impose un grand nombre de fonctions pour avoir un texte lisible et grammaticalement correct. | ||
*Étude | *Étude détaillé du type de données d'entrée pour améliorer les motifs. Pour obtenir un pourcentage plus faible de données perdues et augmenter la quantité d'informations obtenues à partir d’une entrée. | ||
==Exemple== | ==Exemple== | ||
L'exemple | L'exemple basé sur la page de biographie [[Enzo Ferrari]] | ||
'''Données initiales:''' | '''Données initiales:''' | ||
| Ligne 274 : | Ligne 274 : | ||
==Créateurs== | ==Créateurs== | ||
Crée par '''Daniil Morzhakov''' (dmorzhakov) & '''Andrey Piskunov''' (Andrey P). | |||
_/﹋\_<br> | _/﹋\_<br> | ||
Version du 8 mai 2018 à 11:44
SummarizingBot est un bot programmé en langage Python et qui agit sur des pages Wikipast.
Description
Le SummarizingBot crée un résumé, lisible, pour différents personnages sur la base des données saisies dans la partie Biographie de la page Wiki de chaque personnage (tous les personnages traités se trouvent dans la page Wiki Biographies). Le volume approximatif du résume est de 200 mots. La taille du résume dépend fortement des qualités des données d'origine, acquises de la page du personnage. C'est-à-dire, leur volume (au moins 15 entrées) et l'exactitude de l'entrée (syntaxes du Wiki doivent être respectés).
Le principe clé du bot est l'analyse des données (entrées) en utilisant le concept de Expression Régulière (Regular Expression ou RegExp) pour identifier les différentes parties d’entrée (une ligne de donnée). Grâce à cette analyse, on va obtenir des blocs d'information à partir de laquelle chaque entrée est consisté. Ces blocs sont les suivants : Le bloc du Data, Le bloc de la Ville et, finalement, Le bloc d’information sur l'évènement. Ensuite, on tire les informations supplémentaires de chaque bloc et on les traite avec de différentes fonctions. En ce moment-là, on va comprendre quel type de données on a dans le bloc. Si le bloc est de bonne structure on va continuer à le traiter, sinon on va éliminer ce bloc. On peut facilement appliquer les fonctions pour chaque cas particulier des données dans le bloc pour créer une structure correcte applicable au résume.
La performance du code est telle qu'environ 92,8% de données du totale sont traitées et utilisées pour créer le résume. Ce pourcentage a été calculé comme le rapport entre le nombre total de lignes correctement lues par le code et le nombre total de lignes lues par le code de tous les pages de la Biographie.
Expresion Régulière
^\s?(\d{4}\.?\d{0,2}\.?\d{0,2})(\s?\/\s?)?(([\w\s\-,]+))?\.?\s?(.+)$
Notre modèle de RegExp définit trois blocs principaux par motifs (patterns) suivantes :
- Date
^\s?(\d{4}\.?\d{0,2}\.?\d{0,2})
- Lieu (Ville)
(([\w\s\-,]+))?
- Information (Événement)
s?(.+)
Datum Vérification
On veut fournir quelques exemples du traitement des lignes de données.
[1993.05.23][][] ---> "False'', car on a une ligne vide par rapport à l'information.
[1993.05.23][Milan][Information][Bloc d'information non attendent] ---> "False'', car on a trop de blocs de data.
[1993-1994][Milan][Information] ---> "False'', car on a une date qui ne respecte pas le RegExp pour la date (format pas bon).
[1993.05.23][Milan11][Information] ou [1993.05.23][Quelque part][Information] ---> "False'', car on a un lieu qui n'a pas un bon format (chiffres) ou il y a nombreux espaces dans le série.
Points Critique des Performances
Les points critiques sont les suivants :
- Erreurs dans la saisie des données dans la biographie. Non-respect de la syntaxe posée pour l'entrée dans la Biographie.
- Problème de la langue utilisée. La langue française est rarement utilisée dans les réseaux de neurones artificiels (artificial neural network) qui peuvent créer du texte à partir de données qu'on a.
- La grammaire française est assez compliquée. Ceci impose un grand nombre de fonctions pour avoir un texte lisible et grammaticalement correct.
- Étude détaillé du type de données d'entrée pour améliorer les motifs. Pour obtenir un pourcentage plus faible de données perdues et augmenter la quantité d'informations obtenues à partir d’une entrée.
Exemple
L'exemple basé sur la page de biographie Enzo Ferrari
Données initiales:
=Biographie= *[[1899.02.18]] / [[Maranello]]. [[Naissance]] de [[Enzo Ferrari]]. Mais, en raison d'une terrible tempête de neige, l'enfant ne pourra être déclaré que deux jours plus tard a l'état civil. D'ou son [[anniversaire]] "officiel" le 20 février. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1943]] / [[Modène]], [[Maranello]]. [[Transfert]] de l'usine [[Ferrari]] de [[Modène]] à [[Maranello]]. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1946]] / [[Maranello]]. [[Fondation]] de [[manufacture automobiles]] [[Ferrari Automobiles]] par M.[[Enzo Ferrari]]. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1947.05.11]] / [[Piacenza]]. Première course de la [[Ferrari 125 Sport]] (la première Ferrari de course) sur le circuit de [[Piacenza]]. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1948.10.24]] / [[Garde]]. [[Victoire]] de [[Ferrari]] en circuit au lac de Garde pour la premier fois. Le coureur était [[Giuseppe "Nino" Farina]]. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1952]] [[Victoire]] de [[Ferrari]] le premier titre de champion du monde des conducteurs de [[Formula 1]] avec [[Alberto Ascari]], sur [[Ferrari 500 F2/4 cyl.]]. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1959.09.11]] / [[Maranello]]. [[Annonce]] de M.[[Enzo Ferrari]] que "La firme automobile [[Ferrari]] n'est pas en vente". [http://www.letempsarchives.ch/page/JDG_1959_09_11/4/article/7896662/%22enzo%20ferarri%22] *[[1959.12.30]] / [[Maranello]]. Au cours d'une conférence de presse, M.[[Enzo Ferrari]] envisageait le déplacement a [[Bologne]] des secteurs commercial, administratif et d'assistance sociale de ses établissements. [http://www.letempsarchives.ch/page/JDG_1959_12_30/11/article/7921746/%22enzo%20ferarri%22] *[[1966.12.15]] / [[Maranello]]. [[Annonce]] de M. [[Enzo Ferrari]] que "L'an prochain, nous serons présents sur tous les fronts, y compris la formule deux". [http://www.letempsarchives.ch/page/JDG_1966_12_15/13/article/8004297/%22enzo%20ferarri%22] *[[1967.06.22]] / [[Maranello]]. [[Enzo Ferrari]] frappe contre les nouvelles règles de la course "[[24 Heures du Mans]]". Si nouveau règles va accepte, il ne participera plus a cette épreuve. [http://www.letempsarchives.ch/page/JDG_1967_06_22/10/article/8037412/%22enzo%20ferarri%22] *[[1967.08.18]] / [[Maranello]]. [[Annonce]] de M. [[Enzo Ferrari]] que "Après la mort tragique de [[Lorenzo Bandini]], j'ai décidé de limiter a l'avenir l'activité technique et sportivité de [[Ferrari]]". [http://www.letempsarchives.ch/page/JDG_1967_08_18/8/article/8046595/%22enzo%20ferarri%22] *[[1969.06.23]] / [[Turin]]. [[Annonce]] du communiqué de la firme automobile [[FIAT]], que un accord de participation paritaire a été signé entre M.[[Enzo Ferrari]] et M. [[Giovanni Agnelli]]. [http://www.letempsarchives.ch/page/JDG_1969_06_23/6/article/8184906/%22enzo%20ferarri%22] *[[1969.07.29]] / [[Maranello]]. [[Enzo Ferrari]] a abandonné son poste directeur général. Il a été remplacé par M. [[Francesco Bellicardi]], président de Weber, maison de carburateurs appartenant a [[FIAT]]. [http://www.letempsarchives.ch/page/GDL_1969_07_30/9/article/3446427/%22enzo%20ferarri%22] *[[1986.03.12]] / [[Maranello]]. [[Enzo Ferrari]] présente le nouveau modèle [[Ferrari F1-86]]. [http://www.letempsarchives.ch/page/JDG_1986_03_12/27/article/9128502/%22enzo%20ferarri%22] *[[1988.02.18]] / [[Maranello]]. [[Enzo Ferrari]] fête ses 90 ans. [http://www.letempsarchives.ch/page/GDL_1988_02_23/2/article/4760402/enzo%20ferrari%20naissance] *[[1988.08.14]] / [[Maranello]]. [[Décès]] de [[Enzo Ferrari]]. [http://www.letempsarchives.ch/page/JDG_1988_08_16/1/article/9420659/%22enzo%20ferarri%22]
Résume :
=Résume= Le 1899.02.18 Naissance de Enzo Ferrari. Mais, en raison d'une terrible tempête de neige, l'enfant ne pourra être déclaré que deux jours plus tard a l'état civil. D'ou son anniversaire "officiel" le 20 février. [1] a Maranello. En 1943 Transfert de l'usine Ferrari de Modène à Maranello. [2] a Modène, Maranello. En 1946 Fondation de manufacture automobiles Ferrari Automobiles par M.Enzo Ferrari. [3] a Maranello. Le 1947.05.11 Première course de la Ferrari 125 Sport (la première Ferrari de course) sur lecircuit de Piacenza. [4] a Piacenza. Le 1948.10.24 Victoire de Ferrari en circuit au lac de Garde pour la premier fois. Le coureur était Giuseppe "Nino" Farina. [5] a Garde. Le 1959.09.11 Annonce de M.Enzo Ferrari que "La firme automobile Ferrari n'est pas en vente". [7] a Maranello. Le 1959.12.30 Au cours d'une conférence de presse, M.Enzo Ferrari envisageait le déplacement a Bologne des secteurs commercial, administratif et d'assistance sociale de ses établissements. [8]. Le 1966.12.15 Annonce de M. Enzo Ferrari que "L'an prochain, nous serons présents sur tous les fronts, y compris la formule deux". [9]. Le 1967.06.22 Enzo Ferrari frappe contre les nouvelles règles de la course "24 Heures du Mans". Si nouveau règles va accepte, il ne participera plus a cette épreuve. [10]. Le 1967.08.18 Annonce de M. Enzo Ferrari que "Après la mort tragique de Lorenzo Bandini, j'ai décidé de limiter a l'avenir l'activité technique et sportivité de Ferrari". [11]. Le 1969.06.23 Annonce du communiqué de la firme automobile FIAT, que un accord de participation paritaire a été signé entre M.Enzo Ferrari et M. Giovanni Agnelli. [12] a Turin. Le 1969.07.29 Enzo Ferrari a abandonné son poste directeur général. Il a été remplacé par M. Francesco Bellicardi, président de Weber, maison de carburateurs appartenant a FIAT. [13] a Maranello. Le 1986.03.12 Enzo Ferrari présente le nouveau modèle Ferrari F1-86. [14]. Le 1988.02.18 Enzo Ferrari fête ses 90 ans. [15]. Le 1988.08.14 Décès de Enzo Ferrari. [16].
Code
Code du SummarizingBot
from urllib.request import urlopen
import requests
from urllib.parse import quote
from bs4 import BeautifulSoup
from collections import OrderedDict
from geotext import GeoText
import re
# Login information
user='testbot'
passw='dhbot2017'
baseurl = 'http://wikipast.epfl.ch/wikipast/'
summary = 'Wikipastbot update'
# Login request
payload={'action':'query','format':'json','utf8':'','meta':'tokens','type':'login'}
r1=requests.post(baseurl + 'api.php', data=payload)
# Login confirm
login_token=r1.json()['query']['tokens']['logintoken']
payload={'action':'login','format':'json','utf8':'','lgname':user,'lgpassword':passw,'lgtoken':login_token}
r2=requests.post(baseurl + 'api.php', data=payload, cookies=r1.cookies)
# Get edit token2
params3='?format=json&action=query&meta=tokens&continue='
r3=requests.get(baseurl + 'api.php' + params3, cookies=r2.cookies)
edit_token=r3.json()['query']['tokens']['csrftoken']
edit_cookie=r2.cookies.copy()
edit_cookie.update(r3.cookies)
# Regexp for definet the type of datum with which we work
content_reexp = re.compile("^\s?(\d{4}\.?\d{0,2}\.?\d{0,2})(\s?\/\s?)?(([\w\s\-,]+))?\.?\s?(.+)$") # Pattern for data
reference_reexp = re.compile("\s*\[\d+\]\s*") # Pattern for reference
date_reexp = re.compile("^\d{4}\.?\d{0,2}\.?\d{0,2}") # Pattern to date
# Function to get list of personages
def get_all_personages():
response = urlopen("http://wikipast.epfl.ch/wikipast/index.php/Biographies")
page_source = response.read()
soup = BeautifulSoup(page_source,'html.parser')
result = []
for primitive in soup.findAll("body"):
for tableTag in primitive.findAll("table"):
for trTag in tableTag.findAll("tr"):
for tdTag in trTag.findAll("td"):
for aTag in tdTag.findAll("a"):
if aTag.string != None:
result.append(aTag.string)
for idx, _ in enumerate(result): # idx & _ are name of our values in table of results (1:Andre Breton)
result[idx] = str(result[idx].replace(' ', '_')) # Reformatting the data to get correct link to get access to Biographie
return result
# Function for verification of personage data
def is_valid_personage_line(datum): # Introduce initial values
date = datum[0].strip()
city = None
info = None
# Define the type of datum by their length
if len(datum) == 3: # We have date, city and info
city = datum[1].strip()
info = datum[2].strip()
elif len(datum) == 2: # We have date and info
info = datum[1].strip()
else:
return False
# Validate city & Validate date
if not date_reexp.match(date): # Date don't pass the verification of pattern
return False
if city:
places = GeoText(city)
if len(places.cities) == 0:
if city.count(' ') > 2 or '1' in city: # Check if in place of city we add date or not correct name of city
return False
return True
# Function for generate summarizing of Biographie
def generate_text_for_personage(name, data):
result = ''
last_city = None
for datum in data: # Checking all datum in list of data
date = datum[0]
# Remove last dot from date
if date[-1] == '.': date = date[:-1]
city = datum[1].strip() if len(datum) == 3 else None
info = datum[-1]
# Remove incorrect information
if len(info) < 5: continue
# Remove last dot from datum-info (sentence)
if info[-1] == '.': info = info[:-1]
# Add some prefix to date, to make text more readably
date_prefix = 'En ' if len(date) == 4 else 'Le '
# Removing city in case if city repat for two consecutive datum or put prefix
need_city = city != last_city and city != '-'
city_postfix = ((' a ' + city) if city and need_city else '') + '. '
result += date_prefix + date + ' ' + info + city_postfix # Final info, more readable sentence
last_city = city
return result
personages = get_all_personages() # To get all personages for address to functioon "get_all_personnages"
data = {} # List of key:value for all data find
correct_data_ratio = {} # List of key:value which keep ratio of lossing info for each personnage
# Inital values
total_number_of_content_lines = 0
total_number_of_correct_lines = 0
# Collecting all data from pages of Biograhpie
for personage in personages:
site = ("http://wikipast.epfl.ch/wikipast/index.php/" + quote(personage))
response = urlopen(site)
page_source = response.read()
soup = BeautifulSoup(page_source,'html.parser')
content_div = soup.find(id="mw-content-text") # Defined the principle block of Biographie for each personage
content_lines = content_div.findAll("li") # Defined line of datum
data[personage] = [] # Relate data to personage
total_number_of_content_lines += len(content_lines) # Counting the total number of lines which we find
for content_line in content_lines: # Treatment each line in data we extrect for each personnage
content_text = content_line.get_text() # From datum extract text
content_match = content_reexp.match(content_text) # Checking our extracting text with pattern of text
if content_match: # If checking succeed
findings = content_reexp.findall(content_text)
findings_as_array = [x for xs in findings for x in xs] # Made the array of content and personage
findings_no_duplicates = list(OrderedDict.fromkeys(findings_as_array))
findings_no_duplicates.pop(1) # Removing duplicated datum
# Check if last is a reference
if reference_reexp.match(findings_no_duplicates[-1]): findings_no_duplicates.pop(-1)
if is_valid_personage_line(findings_no_duplicates): data[personage].append(findings_no_duplicates)
if len(content_lines) != 0: correct_data_ratio[personage] = len(data[personage]) / len(content_lines) # The ratio of correct data for personnage
else: correct_data_ratio[personage] = 1 # It's mean that we read zero lines in Biographie of personnage
total_number_of_correct_lines += len(data[personage]) # Counting total number of lines which we can process to use in summarizing
print(generate_text_for_personage(personage, data[personage])) # Checking of text which be used for summarizing
correct_data_ratio_overall = total_number_of_correct_lines / total_number_of_content_lines # Checking percentage of data losing after all iteration
print(correct_data_ratio_overall)
Créateurs
Crée par Daniil Morzhakov (dmorzhakov) & Andrey Piskunov (Andrey P).
_/﹋\_
(҂`_´)
<,︻╦╤─ ҉ - - - - - - —
_/﹋\_