L’autre jour, j’ai voulu identifier le taux de duplication entre deux pages en exploitant le Simhash de Charikar.
(Ceci est un doublon (à peu de choses prêt) de l’article que j’ai publié sur le blog de Babbar)
En l’occurrence, les deux pages correspondaient à la page d’un client et celle d’un de ses prestataire à qui le client envoyait son contenu, aussi la fonctionnalité de Babbar sur la duplication interne n’allait malheureusement pas m’aider, mais je me suis dit que je pouvais utiliser une fonction semblable pour aider le client à identifier le niveau de duplication.
Petit disclaimer tout de même : il s’agit ici d’identifier, sur des pages que je connais déjà, si le contenu allait être considéré comme dupliqué. Il ne s’agit pas de trouver des pages qui me copient sur le web.
Alors comment j’ai voulu m’y prendre ?
Tout d’abord, j’ai récupéré les urls qui pouvaient être concernées et j’en ai fait des couples d’urls (je ne me suis pas embêté à faire des couples correspondants forcément, j’ai pris la liste des urls du client, celle du site partenaire, et j’ai fait une création de couples d’urls en dehors du même host, le code pour ça est ici:)
import argparse
import pandas as pd
import trafilatura
from urllib.parse import urlparse
import itertools
from simhash import Simhash
def fetch_content(url):
downloaded = trafilatura.fetch_url(url)
return trafilatura.extract(downloaded)
def read_urls(filename):
with open(filename, 'r') as file:
return [line.strip() for line in file if line.strip()]
def create_csv(data, filename):
df = pd.DataFrame(data)
df.to_csv(filename, index=False)
def create_excel(data, filename):
df = pd.DataFrame(data)
df.to_excel(filename, index=False)
def get_features(text):
return text.split()
def text_similarity(text1, text2):
hash1 = Simhash(get_features(text1))
hash2 = Simhash(get_features(text2))
return hash1.distance(hash2)
def main(urltxt):
urls = read_urls(urltxt)
urls_contents = []
for url in urls:
content = fetch_content(url)
host = urlparse(url).hostname
urls_contents.append({'host': host, 'url': url, 'contenu': content})
# Save the URLs with their contents to a CSV file
create_csv(urls_contents, 'urls_categorisees.csv')
# Create URL pairs with different hosts
df = pd.DataFrame(urls_contents)
couples = []
for (i, row1), (j, row2) in itertools.combinations(df.iterrows(), 2):
if row1['host'] != row2['host']:
couples.append({'source': row1['url'], 'target': row2['url']})
# Save the URL pairs to a CSV file
create_csv(couples, 'couples.csv')
# Create an Excel file for the texts
input_texts = [{'identifiant': row['url'], 'texte': row['contenu']} for index, row in df.iterrows()]
create_excel(input_texts, 'input-text.xlsx')
# Compute SimHash distances for the URL pairs
df_couples = pd.DataFrame(couples)
df_couples['simhash_distance'] = pd.Series(dtype=int)
df_texts = pd.DataFrame(input_texts)
for index, row in df_couples.iterrows():
source_url = row['source']
target_url = row['target']
source_text = df_texts[df_texts['identifiant'] == source_url]['texte'].iloc[0]
target_text = df_texts[df_texts['identifiant'] == target_url]['texte'].iloc[0]
distance = text_similarity(source_text, target_text)
df_couples.at[index, 'simhash_distance'] = distance
# Save the updated couples with SimHash distances to the CSV file
df_couples.to_csv('couples.csv', index=False)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Process URLs and compare text similarity using SimHash.")
parser.add_argument('--li', '-list-urls', type=str, required=True, help='Txt file with URL lists.')
args = parser.parse_args()
urltxt = args.li
main(urltxt)
Attention, il se peut que vous deviez installer les éléments suivants avant l’exécution du script :
et avant d’exploiter le script, assurez vous d’avoir pandas, trafilatura, simhash et argparse :
pip install pandas trafilatura simhash argparse
à utiliser comme suit :
Copiez le code ci-dessus, collez le dans un fichier texte que vous enregistrez sous “nomdufichier.py” (changez le nom du fichier si besoin mais vous devrez alors changer l’équivalent après). Puis créez votre liste d’urls dans VotreListeDUrl.txt (même commentaire sur le nom du fichier que précédemment).
Ouvrez une invite de commande, naviguez jusqu’au dossier sur lequel vous avez vos deux fichiers (python & txt) et entrez cette commande :
python nomdufichier.py --li VotreListeDUrl.txt
Que va t il se passer?
Vous allez vous retrouver sur ce dossier avec un nouveau fichier csv : couples.csv. lequel va permettre de constituer des paires de pages, ainsi qu’un autre fichier csv : urls_categorisees.csv qui indique les urls ainsi que les sites sur lesquels elles sont.
Enfin on va créer un fichier Excel input-text.xlsx qui va recenser les contenus des urls, qu’on aura extrait avec trafilatura.
Et à partir de là on a tout ce qu’il faut pour calculer la distance de simhash de ces couples d’urls à partir du contenu extrait via trafilatura. Pour des raisons de sauvegarde de mémoire, on ajoute cette distance dans couples.csv (Attention : distance veut dire que plus la métrique est petite, plus les pages sont proches).
Et voilà !