From 5d680ab5a7c9d9e509feca35abbabde169f10096 Mon Sep 17 00:00:00 2001 From: Paul Leclercq Date: Thu, 30 Jan 2025 13:11:27 +0100 Subject: [PATCH 1/4] wip --- README.md | 2 + .../mediatree/detect_keywords.py | 22 ++++++--- .../mediatree/stop_word/main.py | 17 +++++-- test/sitemap/test_keywords.py | 9 ++-- test/sitemap/test_update_pg_keywords.py | 8 ++-- test/stop_word/test_stop_word.py | 46 +++++++++---------- 6 files changed, 61 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 54207397..43c0c2b7 100644 --- a/README.md +++ b/README.md @@ -407,6 +407,8 @@ To prevent advertising keywords to blow up statistics, we remove stop words base The result will be saved inside postgresql table: stop_word. +All stop word context are normalized (accent are removed) to simplify how to compare them with S2T (speed to text) + This table is read by the service "mediatree" to remove stop words from the field "plaintext" to avoid to count them. Env variables used : diff --git a/quotaclimat/data_processing/mediatree/detect_keywords.py b/quotaclimat/data_processing/mediatree/detect_keywords.py index 4b3cb9b8..639cca1d 100644 --- a/quotaclimat/data_processing/mediatree/detect_keywords.py +++ b/quotaclimat/data_processing/mediatree/detect_keywords.py @@ -116,28 +116,36 @@ def replace_word_with_context(text: str, word = "groupe verlaine", length_to_rem return result +def normalize_french(text: str) -> str: + translation_table = str.maketrans("éèêëàáâäôöûüîï", "eeeeaaaaoouuii") + return text.translate(translation_table) + +# Stop word SQL Table have been transformed to normalize them, we have to apply the same normalization when comparing plaintext def remove_stopwords(plaintext: str, stopwords: list[str]) -> str: logging.debug(f"Removing stopwords {plaintext}") if len(stopwords) == 0: logging.warning("Stop words list empty") - + return plaintext + plaintext_normalized = normalize_french(plaintext) + logging.info(f"normalized {plaintext_normalized}") if "groupe verlaine" in plaintext: logging.info(f"special groupe verlaine case") - plaintext = replace_word_with_context(plaintext, word="groupe verlaine") + plaintext_normalized = replace_word_with_context(plaintext_normalized, word="groupe verlaine") if "industries point com" in plaintext: logging.info(f"special industries point com case") - plaintext = replace_word_with_context(plaintext, word="industries point com", length_to_remove=150) + plaintext_normalized = replace_word_with_context(plaintext_normalized, word="industries point com", length_to_remove=150) if "fleuron industrie" in plaintext: logging.info(f"special fleuron industrie com case") - plaintext = replace_word_with_context(plaintext, word="fleuron industrie", length_to_remove=150) + plaintext_normalized = replace_word_with_context(plaintext_normalized, word="fleuron industrie", length_to_remove=150) for word in stopwords: - plaintext = plaintext.replace(word, '') + logging.info(f"Test {normalize_french(word)}") + plaintext_normalized = plaintext_normalized.replace(normalize_french(word), '') - return plaintext + return plaintext_normalized @sentry_sdk.trace def get_themes_keywords_duration(plaintext: str, subtitle_duration: List[str], start: datetime, stop_words: List[str] = []): @@ -152,7 +160,7 @@ def get_themes_keywords_duration(plaintext: str, subtitle_duration: List[str], s logging.debug(f"searching {theme} for {keywords_dict}") matching_words = [] for keyword_dict in keywords_dict: - if is_word_in_sentence(keyword_dict["keyword"], plaitext_without_stopwords): + if is_word_in_sentence(normalize_french(keyword_dict["keyword"]), plaitext_without_stopwords): matching_words.append({"keyword": keyword_dict["keyword"], "category": keyword_dict["category"]}) if matching_words: diff --git a/quotaclimat/data_processing/mediatree/stop_word/main.py b/quotaclimat/data_processing/mediatree/stop_word/main.py index 2a03ad1e..de53b68a 100644 --- a/quotaclimat/data_processing/mediatree/stop_word/main.py +++ b/quotaclimat/data_processing/mediatree/stop_word/main.py @@ -130,7 +130,7 @@ def get_all_repetitive_context_advertising_for_a_keyword( end_date_sql = get_date_sql_query(end_date) #"'2024-12-19 00:00:00.000 +01:00'" sql_query = f""" SELECT SUBSTRING("context_keyword",0,{total_length}) AS "context", - MAX("keyword_id") AS "keyword_id", + MAX("keyword_id") AS "keyword_id", -- enable to check directly on mediatree service COUNT(*) AS "count" FROM ( SELECT @@ -139,10 +139,16 @@ def get_all_repetitive_context_advertising_for_a_keyword( "public"."keywords"."start" AS "start_default_time", "public"."keywords"."theme" AS "theme", "public"."keywords"."id" AS "keyword_id", - SUBSTRING( - REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}',''), -- mediatree transcription pollution - GREATEST(POSITION('{escaped_keyword}' IN "public"."keywords"."plaintext") - {before_context}, 1), -- start position - LEAST({after_context}, LENGTH( "public"."keywords"."plaintext")) -- length of the context + TRIM( + REGEXP_REPLACE( + TRANSLATE( + SUBSTRING( + REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}',''), -- mediatree transcription pollution + GREATEST(POSITION('{escaped_keyword}' IN REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}','')) - {before_context}, 1), -- start position + LEAST({after_context}, LENGTH( REPLACE("public"."keywords"."plaintext",' ',''))) -- length of the context + ) + ,'éèêëàáâäôöûüîï', 'eeeeaaaaoouuii') + ,'^\w{{1,2}}\s+|\s+\w{{1,2}}\s*$', '', 'g') -- removes 1-2 letter words at boundaries ) AS "context_keyword", "public"."keywords"."keywords_with_timestamp" AS "keywords_with_timestamp", "public"."keywords"."number_of_keywords" AS "number_of_keywords", @@ -170,6 +176,7 @@ def get_all_repetitive_context_advertising_for_a_keyword( result = [dict(row) for row in result.mappings()] # add metadata to result for all rows for row in result: + row["context"] = row["context"].strip() row["id"] = get_consistent_hash(row["context"]) # to avoid adding duplicates row["keyword"] = keyword row["channel_title"] = channel_title diff --git a/test/sitemap/test_keywords.py b/test/sitemap/test_keywords.py index 5718f0c4..418c022f 100644 --- a/test/sitemap/test_keywords.py +++ b/test/sitemap/test_keywords.py @@ -11,7 +11,7 @@ def test_get_remove_stopwords_recycler(): ] ad = "nous les recycler pour en faire de nouvelles en fabriquant nous-mêmes du plastique recyclé pour cela nous avons créé trois usines exclusivement dédié au recyclage dès cette année cristallines est capable de recycler autant de bouteilles" - assert remove_stopwords(ad, stop_words_list) == "nous les pour en faire de nouvelles en fabriquant nous-mêmes du plastique recyclé pour cela nous avons créé trois usines exclusivement dédié au recyclage dès cette année cristallines est capable de autant de bouteilles" + assert remove_stopwords(ad, stop_words_list) == "nous les pour en faire de nouvelles en fabriquant nous-memes du plastique recycle pour cela nous avons cree trois usines exclusivement dedie au recyclage des cette annee cristallines est capable de autant de bouteilles" def test_get_remove_stopwords_no_modification(): stop_words_list = [ @@ -28,15 +28,15 @@ def test_remove_stopwords_huile(): "est à fond sur le tri sélectif" ] assert remove_stopwords("l' huile de coude était aussi une énergie renouvelable stéphane est à fond sur le tri sélectif",stop_words_list) \ - == "l' stéphane " + == "l' stephane " def test_remove_stopwords_energie(): plaintext = "quand le prix de l' énergie augmente il y a ceux qui se couvre plus ceux qui sortent moins et il y a ceux qui choisissent d' optimiser leurs énergies panneaux solaires isolations thermique pompes à chaleur chaque jour fleuron industrie parcourt la france pour vous aider à optimiser votre énergie florent industries point com en ce moment la centrale photovoltaïque de trois kilowatts et deux mille cinq cents euros et oui deux deux mille cinq cents euros cents dépêchez euros vous dépêchez vous de réserver votre kit sur fleuron industries point com la rénovation énergétique avec ici pour changer de maison sans changer de maison isolation chauffage solaire plus de confort et d' économie avec ici pas à mal casser pas mal vous avez fait une toute la pâte à modeler la je fais comment une tartine de pâte à modeler sans pâte à modeler c' est pas interdit ça s' appelle dupin juste merci pour le partage le jour où vous aimerez la pâte" output = remove_stopwords(plaintext,STOP_WORDS) # plantext does not contain photovoltaïque - assert "photovoltaïque" not in output - assert "rénovation énergétique" not in output + assert "photovoltaique" not in output + assert "rénovation énergetique" not in output assert "chauffage" not in output def test_remove_stopwords_fleuron(): @@ -49,6 +49,7 @@ def test_remove_stopwords_photovoltaique(): plaintext = "point com en ce moment la centrale photovoltaïque de trois kilowatt et à deux m" output = remove_stopwords(plaintext,STOP_WORDS) # plantext does not contain photovoltaïque + assert "photovoltaique" not in output assert "photovoltaïque" not in output assert len(output) == 0 diff --git a/test/sitemap/test_update_pg_keywords.py b/test/sitemap/test_update_pg_keywords.py index d92d3115..ce00844b 100644 --- a/test/sitemap/test_update_pg_keywords.py +++ b/test/sitemap/test_update_pg_keywords.py @@ -815,9 +815,9 @@ def test_update_only_keywords_that_includes_some_keywords(): "id": "test2", "keyword": "climatique", "channel_title": "TF1", - "context": "lacieux selon les experts question climatique en fait elle dépasse la question ", + "context": "lacieux selon les experts question climatique en fait elle dépasse la question", "count": 19, - "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question "), + "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question"), } ] save_append_stop_word(conn, stop_word_to_save) @@ -1020,9 +1020,9 @@ def test_update_nothing_because_no_keywords_are_included(): "id": "test2", "keyword": "climatique", "channel_title": "TF1", - "context": "lacieux selon les experts question climatique en fait elle dépasse la question ", + "context": "lacieux selon les experts question climatique en fait elle dépasse la question", "count": 19, - "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question "), + "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question"), } ] save_append_stop_word(conn, stop_word_to_save) diff --git a/test/stop_word/test_stop_word.py b/test/stop_word/test_stop_word.py index ea80e6f0..ba2b8e05 100644 --- a/test/stop_word/test_stop_word.py +++ b/test/stop_word/test_stop_word.py @@ -67,8 +67,8 @@ def test_stop_word_get_all_repetitive_context_advertising_for_a_keyword_default( 'keyword_id': 'f9761d34d1e9adfc44bab9ad220e216b1a9a6a0aca44c39c5fab5115fe098d79', 'start_date': start_date, "channel_title": "France 2", - "context": " avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa", - 'id': '4bd208a8e3b14f2ac46e272647729f05fb7588e427ce12d99bde6d5698415970', + "context": "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas", + 'id': get_consistent_hash("avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas"), "count": 20 # min number of repetition } ] @@ -88,39 +88,38 @@ def test_stop_word_get_all_repetitive_context_advertising_for_a_keyword_utf8_min 'channel_title': 'TF1', 'keyword_id': 'eb0c12caa8a290c8e8a4a4d17e0ee5a943986fc29d14f54f0e1e30becd6aae32', 'start_date': start_date, - 'context': "agroécologie végétation dans l' antre des las vegas raiders c' est ici que se j", + 'context': "agroecologie vegetation dans l' antre des las vegas raiders c' est ici que se j", 'count': 1, - 'id': '06130961a8c4556edfd80084d9cf413819b8ba2d91dc8f90cca888585fac8adc', + 'id': get_consistent_hash("agroecologie vegetation dans l' antre des las vegas raiders c' est ici que se j"), 'keyword': 'agroécologie', }, { 'channel_title': 'TF1', 'keyword_id': '0b4d8ca4c5d512acb1fac4731e8cb46dde85be7e875c7510c84cc6b6d4ada2f4', 'start_date': start_date, - 'context': "agroécologie végétation hasard peter aussi mène contre sébastien à l' heure deu", + 'context': "agroecologie vegetation hasard peter aussi mene contre sebastien a l' heure deu", 'count': 1, 'keyword': 'agroécologie', - "id" : get_consistent_hash("agroécologie végétation hasard peter aussi mène contre sébastien à l' heure deu") + "id" : get_consistent_hash("agroecologie vegetation hasard peter aussi mene contre sebastien a l' heure deu") }, { 'channel_title': 'TF1', 'keyword_id': '94a088d85f338c5857e64c0ab8b4f3232db3a52d906264eea712701a2ad31cd4', 'start_date': start_date, - 'context': 'climatique agroécologie est le hameau de la cuisine pensez à ce sujet ' + 'context': 'climatique agroecologie est le hameau de la cuisine pensez a ce sujet ' 'quinze an', 'count': 1, 'keyword': 'agroécologie', - "id" : get_consistent_hash('climatique agroécologie est le hameau de la cuisine pensez à ce sujet quinze an') + "id" : get_consistent_hash('climatique agroecologie est le hameau de la cuisine pensez a ce sujet quinze an') }, { 'channel_title': 'TF1', 'keyword_id': '1571457f2fb35ff37ca3cb9eaa9040606497baaf5e6ad5d6a42c69b12c596596', 'start_date': start_date, - 'context': "climatique agroécologie moment-là parce que l' éblouissement au " - 'balcon de bucki', + 'context': "climatique agroecologie moment-la parce que l' eblouissement au balcon de bucki", 'count': 1, 'keyword': 'agroécologie', - "id" : get_consistent_hash("climatique agroécologie moment-là parce que l' éblouissement au balcon de bucki") + "id" : get_consistent_hash("climatique agroecologie moment-la parce que l' eblouissement au balcon de bucki") }, ] keyword1 = "agroécologie" # not used enough in short_mediatree.json @@ -186,24 +185,25 @@ def test_stop_word_get_repetitive_context_advertising(): } ] ) - + context1 = "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas" + context2 = "lacieux selon les experts question climatique en fait elle depasse la question" excepted = [ { "keyword_id": "f9761d34d1e9adfc44bab9ad220e216b1a9a6a0aca44c39c5fab5115fe098d79", "keyword": "replantation", "channel_title": "France 2", - "context": " avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa", + "context": context1, "count": 20, - "id" : get_consistent_hash(" avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa"), + "id" : get_consistent_hash(context1), 'start_date': start_date, }, { "keyword_id": "f9761d34d1e9adfc44bab9ad220e216b1a9a6a0aca44c39c5fab5115fe098d79", "keyword": "climatique", "channel_title": "TF1", - "context": "lacieux selon les experts question climatique en fait elle dépasse la question ", + "context": context2, "count": 20, - "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question "), + "id" : get_consistent_hash(context2), 'start_date': start_date, } ] @@ -221,18 +221,18 @@ def test_stop_word_save_append_stop_word(): "id": "test1", "keyword": "replantation", "channel_title": "France 2", - "context": " avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa", + "context": "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas", "count": 20, - "id" : get_consistent_hash(" avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa"), + "id" : get_consistent_hash("avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas"), }, { "keyword_id": "fake_id", "id": "test2", "keyword": "climatique", "channel_title": "TF1", - "context": "lacieux selon les experts question climatique en fait elle dépasse la question ", + "context": "lacieux selon les experts question climatique en fait elle dépasse la question", "count": 19, - "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question "), + "id" : get_consistent_hash("lacieux selon les experts question climatique en fait elle dépasse la question"), }, { "keyword_id": "fake_id", @@ -256,8 +256,8 @@ def test_stop_word_save_append_stop_word(): assert stop_words[1].count == 19 assert stop_words[0].channel_title == "France 2" assert stop_words[1].channel_title == "TF1" - assert stop_words[0].context == " avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa" - assert stop_words[1].context == "lacieux selon les experts question climatique en fait elle dépasse la question " + assert stop_words[0].context == "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas" + assert stop_words[1].context == "lacieux selon les experts question climatique en fait elle dépasse la question" assert stop_words[2].context == "empty_keyword" assert stop_words[2].keyword == None @@ -272,7 +272,7 @@ def test_stop_word_main(): def test_stop_word_is_already_known_stop_word(): - context1_avait= " avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa" + context1_avait= "avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pa" context2_avais= " avais promis de lancer un plan de replantation euh hélas pas pu tout s' est pa" assert is_already_known_stop_word(context1_avait, context2_avais) == True From 2d4a2ef92b714e779148a56c096c4586f9f21ad9 Mon Sep 17 00:00:00 2001 From: Paul Leclercq Date: Wed, 5 Feb 2025 15:49:30 +0100 Subject: [PATCH 2/4] refacto: do not normalize french accents --- .../mediatree/detect_keywords.py | 35 +++++++++---------- .../mediatree/stop_word/main.py | 17 ++++----- test/stop_word/test_stop_word.py | 30 ++++++++-------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/quotaclimat/data_processing/mediatree/detect_keywords.py b/quotaclimat/data_processing/mediatree/detect_keywords.py index 639cca1d..c3b3c585 100644 --- a/quotaclimat/data_processing/mediatree/detect_keywords.py +++ b/quotaclimat/data_processing/mediatree/detect_keywords.py @@ -116,36 +116,38 @@ def replace_word_with_context(text: str, word = "groupe verlaine", length_to_rem return result -def normalize_french(text: str) -> str: - translation_table = str.maketrans("éèêëàáâäôöûüîï", "eeeeaaaaoouuii") - return text.translate(translation_table) - -# Stop word SQL Table have been transformed to normalize them, we have to apply the same normalization when comparing plaintext def remove_stopwords(plaintext: str, stopwords: list[str]) -> str: logging.debug(f"Removing stopwords {plaintext}") if len(stopwords) == 0: logging.warning("Stop words list empty") return plaintext - plaintext_normalized = normalize_french(plaintext) - logging.info(f"normalized {plaintext_normalized}") + if "groupe verlaine" in plaintext: logging.info(f"special groupe verlaine case") - plaintext_normalized = replace_word_with_context(plaintext_normalized, word="groupe verlaine") + plaintext = replace_word_with_context(plaintext, word="groupe verlaine") if "industries point com" in plaintext: logging.info(f"special industries point com case") - plaintext_normalized = replace_word_with_context(plaintext_normalized, word="industries point com", length_to_remove=150) + plaintext = replace_word_with_context(plaintext, word="industries point com", length_to_remove=150) if "fleuron industrie" in plaintext: logging.info(f"special fleuron industrie com case") - plaintext_normalized = replace_word_with_context(plaintext_normalized, word="fleuron industrie", length_to_remove=150) + plaintext = replace_word_with_context(plaintext, word="fleuron industrie", length_to_remove=150) for word in stopwords: - logging.info(f"Test {normalize_french(word)}") - plaintext_normalized = plaintext_normalized.replace(normalize_french(word), '') + logging.info(f"Test {word}") + plaintext = plaintext.replace(word, '') - return plaintext_normalized + return plaintext + +def get_detected_keywords(plaitext_without_stopwords: str, keywords_dict): + matching_words = [] + for keyword_dict in keywords_dict: + if is_word_in_sentence(keyword_dict["keyword"], plaitext_without_stopwords): + matching_words.append({"keyword": keyword_dict["keyword"], "category": keyword_dict["category"]}) + + return matching_words @sentry_sdk.trace def get_themes_keywords_duration(plaintext: str, subtitle_duration: List[str], start: datetime, stop_words: List[str] = []): @@ -158,11 +160,8 @@ def get_themes_keywords_duration(plaintext: str, subtitle_duration: List[str], s for theme, keywords_dict in THEME_KEYWORDS.items(): logging.debug(f"searching {theme} for {keywords_dict}") - matching_words = [] - for keyword_dict in keywords_dict: - if is_word_in_sentence(normalize_french(keyword_dict["keyword"]), plaitext_without_stopwords): - matching_words.append({"keyword": keyword_dict["keyword"], "category": keyword_dict["category"]}) - + matching_words = get_detected_keywords(plaitext_without_stopwords, keywords_dict) + if matching_words: logging.debug(f"theme found : {theme} with word {matching_words}") diff --git a/quotaclimat/data_processing/mediatree/stop_word/main.py b/quotaclimat/data_processing/mediatree/stop_word/main.py index de53b68a..3be6a86e 100644 --- a/quotaclimat/data_processing/mediatree/stop_word/main.py +++ b/quotaclimat/data_processing/mediatree/stop_word/main.py @@ -55,7 +55,10 @@ def get_all_stop_word(session: Session, offset: int = 0, batch_size: int = 50000 func.timezone('UTC', Stop_Word.created_at).label('created_at'), func.timezone('UTC', Stop_Word.updated_at).label('updated_at') ).select_from(Stop_Word) \ - .order_by(Stop_Word.count.desc(), Stop_Word.created_at) \ + .order_by(Stop_Word.count.desc(), + func.length(Stop_Word.context).desc(), + Stop_Word.created_at + ) \ .limit(batch_size).offset(offset) if validated_only: @@ -141,13 +144,11 @@ def get_all_repetitive_context_advertising_for_a_keyword( "public"."keywords"."id" AS "keyword_id", TRIM( REGEXP_REPLACE( - TRANSLATE( - SUBSTRING( - REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}',''), -- mediatree transcription pollution - GREATEST(POSITION('{escaped_keyword}' IN REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}','')) - {before_context}, 1), -- start position - LEAST({after_context}, LENGTH( REPLACE("public"."keywords"."plaintext",' ',''))) -- length of the context - ) - ,'éèêëàáâäôöûüîï', 'eeeeaaaaoouuii') + SUBSTRING( + REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}',''), -- mediatree transcription pollution + GREATEST(POSITION('{escaped_keyword}' IN REPLACE("public"."keywords"."plaintext",'{MEDIATREE_TRANSCRIPTION_PROBLEM}','')) - {before_context}, 1), -- start position + LEAST({after_context}, LENGTH( REPLACE("public"."keywords"."plaintext",' ',''))) -- length of the context + ) ,'^\w{{1,2}}\s+|\s+\w{{1,2}}\s*$', '', 'g') -- removes 1-2 letter words at boundaries ) AS "context_keyword", "public"."keywords"."keywords_with_timestamp" AS "keywords_with_timestamp", diff --git a/test/stop_word/test_stop_word.py b/test/stop_word/test_stop_word.py index ba2b8e05..0d2b23a9 100644 --- a/test/stop_word/test_stop_word.py +++ b/test/stop_word/test_stop_word.py @@ -67,8 +67,8 @@ def test_stop_word_get_all_repetitive_context_advertising_for_a_keyword_default( 'keyword_id': 'f9761d34d1e9adfc44bab9ad220e216b1a9a6a0aca44c39c5fab5115fe098d79', 'start_date': start_date, "channel_title": "France 2", - "context": "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas", - 'id': get_consistent_hash("avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas"), + "context": "avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pas", + 'id': get_consistent_hash("avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pas"), "count": 20 # min number of repetition } ] @@ -88,38 +88,38 @@ def test_stop_word_get_all_repetitive_context_advertising_for_a_keyword_utf8_min 'channel_title': 'TF1', 'keyword_id': 'eb0c12caa8a290c8e8a4a4d17e0ee5a943986fc29d14f54f0e1e30becd6aae32', 'start_date': start_date, - 'context': "agroecologie vegetation dans l' antre des las vegas raiders c' est ici que se j", + 'context': "agroécologie végétation dans l' antre des las vegas raiders c' est ici que se j", 'count': 1, - 'id': get_consistent_hash("agroecologie vegetation dans l' antre des las vegas raiders c' est ici que se j"), + 'id': get_consistent_hash("agroécologie végétation dans l' antre des las vegas raiders c' est ici que se j"), 'keyword': 'agroécologie', }, { 'channel_title': 'TF1', 'keyword_id': '0b4d8ca4c5d512acb1fac4731e8cb46dde85be7e875c7510c84cc6b6d4ada2f4', 'start_date': start_date, - 'context': "agroecologie vegetation hasard peter aussi mene contre sebastien a l' heure deu", + 'context': "agroécologie végétation hasard peter aussi mène contre sébastien à l' heure deu", 'count': 1, 'keyword': 'agroécologie', - "id" : get_consistent_hash("agroecologie vegetation hasard peter aussi mene contre sebastien a l' heure deu") + "id" : get_consistent_hash("agroécologie végétation hasard peter aussi mène contre sébastien à l' heure deu") }, { 'channel_title': 'TF1', 'keyword_id': '94a088d85f338c5857e64c0ab8b4f3232db3a52d906264eea712701a2ad31cd4', 'start_date': start_date, - 'context': 'climatique agroecologie est le hameau de la cuisine pensez a ce sujet ' + 'context': 'climatique agroécologie est le hameau de la cuisine pensez à ce sujet ' 'quinze an', 'count': 1, 'keyword': 'agroécologie', - "id" : get_consistent_hash('climatique agroecologie est le hameau de la cuisine pensez a ce sujet quinze an') + "id" : get_consistent_hash('climatique agroécologie est le hameau de la cuisine pensez à ce sujet quinze an') }, { 'channel_title': 'TF1', 'keyword_id': '1571457f2fb35ff37ca3cb9eaa9040606497baaf5e6ad5d6a42c69b12c596596', 'start_date': start_date, - 'context': "climatique agroecologie moment-la parce que l' eblouissement au balcon de bucki", + 'context': "climatique agroécologie moment-là parce que l' éblouissement au balcon de bucki", 'count': 1, 'keyword': 'agroécologie', - "id" : get_consistent_hash("climatique agroecologie moment-la parce que l' eblouissement au balcon de bucki") + "id" : get_consistent_hash("climatique agroécologie moment-là parce que l' éblouissement au balcon de bucki") }, ] keyword1 = "agroécologie" # not used enough in short_mediatree.json @@ -185,8 +185,8 @@ def test_stop_word_get_repetitive_context_advertising(): } ] ) - context1 = "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas" - context2 = "lacieux selon les experts question climatique en fait elle depasse la question" + context1 = "avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pas" + context2 = "lacieux selon les experts question climatique en fait elle dépasse la question" excepted = [ { "keyword_id": "f9761d34d1e9adfc44bab9ad220e216b1a9a6a0aca44c39c5fab5115fe098d79", @@ -221,9 +221,9 @@ def test_stop_word_save_append_stop_word(): "id": "test1", "keyword": "replantation", "channel_title": "France 2", - "context": "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas", + "context": "avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pas", "count": 20, - "id" : get_consistent_hash("avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas"), + "id" : get_consistent_hash("avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pas"), }, { "keyword_id": "fake_id", @@ -256,7 +256,7 @@ def test_stop_word_save_append_stop_word(): assert stop_words[1].count == 19 assert stop_words[0].channel_title == "France 2" assert stop_words[1].channel_title == "TF1" - assert stop_words[0].context == "avait promis de lancer un plan de replantation euh helas pas pu tout s' est pas" + assert stop_words[0].context == "avait promis de lancer un plan de replantation euh hélas pas pu tout s' est pas" assert stop_words[1].context == "lacieux selon les experts question climatique en fait elle dépasse la question" assert stop_words[2].context == "empty_keyword" assert stop_words[2].keyword == None From ab072c11834673a2bc33095b3e811f22b23fa24b Mon Sep 17 00:00:00 2001 From: Paul Leclercq Date: Wed, 5 Feb 2025 15:56:22 +0100 Subject: [PATCH 3/4] test: remove accent test --- test/sitemap/test_keywords.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/sitemap/test_keywords.py b/test/sitemap/test_keywords.py index 418c022f..eeec4129 100644 --- a/test/sitemap/test_keywords.py +++ b/test/sitemap/test_keywords.py @@ -11,7 +11,7 @@ def test_get_remove_stopwords_recycler(): ] ad = "nous les recycler pour en faire de nouvelles en fabriquant nous-mêmes du plastique recyclé pour cela nous avons créé trois usines exclusivement dédié au recyclage dès cette année cristallines est capable de recycler autant de bouteilles" - assert remove_stopwords(ad, stop_words_list) == "nous les pour en faire de nouvelles en fabriquant nous-memes du plastique recycle pour cela nous avons cree trois usines exclusivement dedie au recyclage des cette annee cristallines est capable de autant de bouteilles" + assert remove_stopwords(ad, stop_words_list) == "nous les pour en faire de nouvelles en fabriquant nous-mêmes du plastique recyclé pour cela nous avons créé trois usines exclusivement dédié au recyclage dès cette année cristallines est capable de autant de bouteilles" def test_get_remove_stopwords_no_modification(): stop_words_list = [ @@ -28,7 +28,7 @@ def test_remove_stopwords_huile(): "est à fond sur le tri sélectif" ] assert remove_stopwords("l' huile de coude était aussi une énergie renouvelable stéphane est à fond sur le tri sélectif",stop_words_list) \ - == "l' stephane " + == "l' stéphane " def test_remove_stopwords_energie(): From ed50527be4d181ce1ac100f28916477120138f11 Mon Sep 17 00:00:00 2001 From: Paul Leclercq Date: Wed, 5 Feb 2025 16:04:12 +0100 Subject: [PATCH 4/4] review: readme & tests --- README.md | 2 -- test/sitemap/test_keywords.py | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 43c0c2b7..54207397 100644 --- a/README.md +++ b/README.md @@ -407,8 +407,6 @@ To prevent advertising keywords to blow up statistics, we remove stop words base The result will be saved inside postgresql table: stop_word. -All stop word context are normalized (accent are removed) to simplify how to compare them with S2T (speed to text) - This table is read by the service "mediatree" to remove stop words from the field "plaintext" to avoid to count them. Env variables used : diff --git a/test/sitemap/test_keywords.py b/test/sitemap/test_keywords.py index eeec4129..a7de89fc 100644 --- a/test/sitemap/test_keywords.py +++ b/test/sitemap/test_keywords.py @@ -35,7 +35,7 @@ def test_remove_stopwords_energie(): plaintext = "quand le prix de l' énergie augmente il y a ceux qui se couvre plus ceux qui sortent moins et il y a ceux qui choisissent d' optimiser leurs énergies panneaux solaires isolations thermique pompes à chaleur chaque jour fleuron industrie parcourt la france pour vous aider à optimiser votre énergie florent industries point com en ce moment la centrale photovoltaïque de trois kilowatts et deux mille cinq cents euros et oui deux deux mille cinq cents euros cents dépêchez euros vous dépêchez vous de réserver votre kit sur fleuron industries point com la rénovation énergétique avec ici pour changer de maison sans changer de maison isolation chauffage solaire plus de confort et d' économie avec ici pas à mal casser pas mal vous avez fait une toute la pâte à modeler la je fais comment une tartine de pâte à modeler sans pâte à modeler c' est pas interdit ça s' appelle dupin juste merci pour le partage le jour où vous aimerez la pâte" output = remove_stopwords(plaintext,STOP_WORDS) # plantext does not contain photovoltaïque - assert "photovoltaique" not in output + assert "photovoltaïque" not in output assert "rénovation énergetique" not in output assert "chauffage" not in output @@ -49,7 +49,6 @@ def test_remove_stopwords_photovoltaique(): plaintext = "point com en ce moment la centrale photovoltaïque de trois kilowatt et à deux m" output = remove_stopwords(plaintext,STOP_WORDS) # plantext does not contain photovoltaïque - assert "photovoltaique" not in output assert "photovoltaïque" not in output assert len(output) == 0