Statistiques sur les inscriptions, bannissements et signalements

Bref, statistiques sur tout ce qui concerne le spam !

On est plusieurs à avoir constaté une augmentation du spam sur Zeste de Savoir ces dernières années. J’ai eu envie d’estimer l’ampleur de ce fléau donc j’ai fait quelques statistiques !

Analyse des inscriptions

Comptes créés… depuis la création du site en 2014 en 2015 en 2016 en 2017 en 2018 en 2019 en 2020 en 2021 en 2022 en 2023 en 2024
Comptes utilisateurs 30328 (100 %) 1526 (100 %) 2465 (100 %) 2629 (100 %) 2736 (100 %) 2733 (100 %) 2891 (100 %) 3400 (100 %) 3149 (100 %) 3012 (100 %) 3028 (100 %) 2739 (100 %)
Comptes utilisateurs activés 27017 (89 %) 1430 (94 %) 2243 (91 %) 2373 (90 %) 2480 (91 %) 2306 (84 %) 2535 (88 %) 3030 (89 %) 2782 (88 %) 2700 (90 %) 2708 (89 %) 2411 (88 %)
Comptes utilisateurs activés et bannis 3726 (12 %) 8 (1 %) 75 (3 %) 52 (2 %) 49 (2 %) 294 (11 %) 308 (11 %) 458 (13 %) 453 (14 %) 533 (18 %) 802 (26 %) 688 (25 %)
Analyse des inscriptions

Les inscriptions sont relativement stables depuis 2015 avec une moyenne 2900 comptes créés chaque année. Environ 10% de ces comptes sont inactifs, c’est-à-dire que l’adresse de courriel n’a pas été validée par l’utilisateur en cliquant sur le lien reçu par courriel. Je n’imaginais pas que ce nombre soit aussi élevé ! Enfin, on observe depuis 2018 une croissance des comptes bannis de façon permanente. Ils représentent un quart des inscriptions ces deux dernières années !

Analyse des inscriptions via les réseaux sociaux

Comptes créés… depuis la création du site en 2014 en 2015 en 2016 en 2017 en 2018 en 2019 en 2020 en 2021 en 2022 en 2023 en 2024
Utilisateurs inscrits 27017 1430 2243 2373 2480 2306 2535 3030 2782 2700 2708 2411
Utilisateurs inscrits via les réseaux sociaux 11162 (100 %) 31 (100 %) 518 (100 %) 898 (100 %) 1221 (100 %) 1001 (100 %) 802 (100 %) 1270 (100 %) 1338 (100 %) 1345 (100 %) 1449 (100 %) 1278 (100 %)
Utilisateurs inscrits via les réseaux sociaux et bannis 1224 (11 %) 0 (0 %) 9 (2 %) 14 (2 %) 9 (1 %) 95 (9 %) 50 (6 %) 100 (8 %) 150 (11 %) 184 (14 %) 320 (22 %) 291 (23 %)
Utilisateurs inscrits via Google 8706 (78 %) 26 (84 %) 502 (97 %) 616 (69 %) 684 (56 %) 640 (64 %) 534 (67 %) 884 (70 %) 1112 (83 %) 1175 (87 %) 1328 (92 %) 1194 (93 %)
Utilisateurs inscrits via Facebook 2446 (22 %) 5 (16 %) 6 (1 %) 282 (31 %) 537 (44 %) 361 (36 %) 268 (33 %) 386 (30 %) 226 (17 %) 170 (13 %) 121 (8 %) 84 (7 %)
Utilisateurs inscrits via Twitter1 10 (0 %) 0 (0 %) 10 (2 %) 0 (0 %) 0 (0 %) 0 (0 %) 0 (0 %) 0 (0 %) 0 (0 %) 0 (0 %) 0 (0 %) 0 (0 %)
Analyse des inscriptions via les réseaux sociaux

Environ 40 % des comptes créés sur le site l’ont été via les réseaux sociaux et la moitié des inscriptions se font via les réseaux sociaux ces dernières années. 80 % de ces comptes proviennent de Google et 20 % de Facebook.

On retrouve dans ce tableau les même proportions de comptes bannis de façon permanente que dans le tableau précédent : 10 % des comptes depuis la création du site et environ 25 % ces deux dernières années.


  1. La possibilité de s’inscrire via Twitter a été enlevée en février 2015.

Analyse des bannissements permanents

Bannissements de comptes créés… depuis la création du site en 2014 en 2015 en 2016 en 2017 en 2018 en 2019 en 2020 en 2021 en 2022 en 2023 en 2024
Bannissements permanents 37782 (100 %) 7 (100 %) 86 (100 %) 52 (100 %) 49 (100 %) 301 (100 %) 310 (100 %) 466 (100 %) 459 (100 %) 536 (100 %) 808 (100 %) 698 (100 %)
Bannissements permanents pour spam1 3341 (88 %) 5 (71 %) 29 (34 %) 29 (56 %) 34 (69 %) 208 (69 %) 257 (83 %) 403 (86 %) 420 (92 %) 497 (93 %) 776 (96 %) 677 (97 %)
Bannissements permanents pour spam1 (moins de 7 jours après l’inscription) 2855 (76 %) 3 (43 %) 28 (33 %) 21 (40 %) 23 (47 %) 100 (33 %) 213 (69 %) 371 (80 %) 385 (84 %) 450 (84 %) 667 (83 %) 588 (84 %)
Bannissements permanents pour spam1 (moins de 1 jour après l’inscription) 2624 (69 %) 2 (29 %) 23 (27 %) 21 (40 %) 21 (43 %) 75 (25 %) 159 (51 %) 336 (72 %) 367 (80 %) 423 (79 %) 631 (78 %) 560 (80 %)
Bannissements permanents pour spam1 (moins de 1 heure après l’inscription) 1371 (36 %) 2 (29 %) 18 (21 %) 17 (33 %) 11 (22 %) 46 (15 %) 65 (21 %) 178 (38 %) 191 (42 %) 221 (41 %) 310 (38 %) 309 (44 %)
Analyse des bannissements permanents

Ces deux dernières années, plus de 95 % des bannissements le sont pour cause de spam (publicité, arnaque…) avec une très bonne réactivité de la part de l’équipe du site car 80 % de ces bannissements ont lieu moins d’un jour après l’inscription et 45 % moins d’une heure après celle-ci !


  1. Je n’ai gardé ici que les bannissements dont l’explication donnée par le modérateur contient le mot 'spam’.
  2. Il y a bien 3778 bannissements permanents mais seulement 3726 comptes utilisateurs activés et bannis (cf. le premier tableau du billet). Un bannissement correspond ici à l’action de bannir et non pas à l’état actuel d’un compte utilisateur. Cette différence numéraire s’explique donc par la possibilité d’enlever un bannissement (puis éventuellement de le remettre… puis de l’enlever à nouveau…).

Analyse des signalements

Signalements émis… depuis la création du site en 2016 en 2017 en 2018 en 2019 en 2020 en 2021 en 2022 en 2023 en 2024
Signalements 6017 (100 %) 58 (100 %) 553 (100 %) 529 (100 %) 557 (100 %) 782 (100 %) 614 (100 %) 914 (100 %) 1068 (100 %) 937 (100 %)
Signalements de profils 1242 (21 %) 0 (0 %) 0 (0 %) 0 (0 %) 50 (9 %) 91 (12 %) 70 (11 %) 355 (39 %) 323 (30 %) 351 (37 %)
Signalements de messages sur le forum 3901 (65 %) 57 (98 %) 473 (86 %) 441 (83 %) 437 (78 %) 623 (80 %) 474 (77 %) 459 (50 %) 508 (48 %) 426 (45 %)
Signalements de contenus 122 (2 %) 0 (0 %) 34 (6 %) 25 (5 %) 20 (4 %) 6 (1 %) 19 (3 %) 7 (1 %) 3 (0 %) 8 (1 %)
Signalements de commentaires 752 (12 %) 1 (2 %) 46 (8 %) 63 (12 %) 50 (9 %) 62 (8 %) 51 (8 %) 93 (10 %) 234 (22 %) 152 (16 %)
Analyse des signalements

Plus de la moitié des signalements émis concernent des messages du forum et leur évolution est stable avec environ 450 signalements chaque année depuis 2015. Les signalements de profils et de commentaires ont eux nettement augmentés ces trois dernières années.

Analyse des signalements émis par l'antispam des biographies

Signalements émis… depuis la création du site en 2019 en 2020 en 2021 en 2022 en 2023 en 2024
Signalements de profils 1242 (100 %) 50 (100 %) 91 (100 %) 70 (100 %) 355 (100 %) 323 (100 %) 351 (100 %)
Signalements de profils par l’antispam des biographies 783 (63 %) 0 (0 %) 0 (0 %) 0 (0 %) 252 (71 %) 261 (81 %) 268 (76 %)
Signalements de profils par l’antispam des biographies suivi d’un bannissement 775 (62 %) 0 (0 %) 0 (0 %) 0 (0 %) 247 (70 %) 260 (80 %) 266 (76 %)
Analyse des signalements émis par l’antispam des biographiques

Depuis juin 2020, l’antispam des biographies essaie de détecter le spam dans les biographies des comptes créés récemment et notifie les modérateurs lorsqu’une biographie lui semble suspecte. Au début, la notification se faisait par message privé à un groupe de modérateurs, mais depuis janvier 2022 le script utilise la fonction "Signaler" des profils. S’il est difficile d’estimer le nombre de faux négatifs, il n’y a en tous cas que très peu de faux positifs !


Code source du script Python qui a extrait ces statistiques de la base de données
from datetime import timedelta

from django.conf import settings
from django.contrib.auth.models import User, Group
from django.db.models import ExpressionWrapper, F, DurationField
from social_django.models import UserSocialAuth

from zds.member.models import Profile, Ban
from zds.utils.models import Alert

groupe_des_robots = Group.objects.get(name=settings.ZDS_APP["member"]["bot_group"])

antispam_user = User.objects.get(username="Antispam des biographies")

def print_to_file(text):
    with open("/opt/zds/table_output.md", "a") as f:
        f.write(text)

def print_table(base, abscisses, ordonnées, coin=" ", titre=None):
    table = "\n" + " | ".join([coin] + list(abscisses.keys())) + "\n" + "|".join(["---"]*(len(abscisses)+1)) + "\n"
    for index_y, (titre_y, filtre_y) in enumerate(ordonnées.items()):
        table += titre_y
        if index_y == 0: # première ligne
            valeurs_max = []
        for index_x, filtre_x in enumerate(abscisses.values()):
            valeur = filtre_y(filtre_x(base)).count()
            if index_y == 0: # première ligne
                valeurs_max += [valeur]
            try:
                pourcentage = round(valeur / valeurs_max[index_x] * 100)
            except ZeroDivisionError:
                pourcentage = 0
            table += f" | {valeur} ({pourcentage} %)"
        table += "\n"
    if titre:
        table += f"Table: {titre}\n"
    table += "\n\n"
    print_to_file(table)

### Analyse des comptes utilisateurs

base = Profile.objects.exclude(user__groups__in=[groupe_des_robots])
abscisses = {
    "depuis la création du site": lambda x: x
} | {
    f"en {année}": lambda x, année=année: x.filter(user__date_joined__year=année) for année in range(2014, 2025)
}
ordonnées = {
    "Comptes utilisateurs": lambda x: x,
    "Comptes utilisateurs activés[^utilisateurs-activés]": lambda x: x.filter(user__is_active=True),
    "Comptes utilisateurs activés[^utilisateurs-activés] et bannis": lambda x: x.filter(user__is_active=True).filter(can_read=False).filter(end_ban_read=None),
}
coin = "Comptes créés..."
titre = "Analyse des comptes utilisateurs"

print_table(base, abscisses, ordonnées, coin, titre)

print_to_file("\n[^utilisateurs-activés]: Les comptes utilisateurs ne sont activés qu'une fois que l'adresse de courriel a été vérifiée (donc que l'utilisateur a cliqué sur un lien reçu par courriel).\n")

## Utilisateurs inscrits via les réseaux sociaux

base = UserSocialAuth.objects.filter(user__is_active=True)
abscisses = {
    "depuis la création du site": lambda x: x
} | {
    f"en {année}": lambda x, année=année: x.filter(user__date_joined__year=année) for année in range(2014, 2025)
}
ordonnées = {
    "Utilisateurs inscrits via les réseaux sociaux": lambda x: x,
    "Utilisateurs inscrits via les réseaux sociaux et bannis": lambda x: x.filter(user__profile__can_read=False).filter(user__profile__end_ban_read=None),
    "Utilisateurs inscrits via Google": lambda x: x.filter(provider="google-oauth2"),
    "Utilisateurs inscrits via Facebook": lambda x: x.filter(provider="facebook"),
    "Utilisateurs inscrits via Twitter[^twitter]": lambda x: x.filter(provider="twitter"),
}
coin = "Comptes créés..."
titre = "Analyse des utilisateurs inscrits via les réseaux sociaux"

print_table(base, abscisses, ordonnées, coin, titre)

print_to_file("\n[^twitter]: La possibilité de s'inscrire via Twitter a été enlevée en février 2015.\n")

### Analyse des bannissements permanents

base = Ban.objects.annotate(depuis_inscription=ExpressionWrapper(F("pubdate") - F("user__date_joined"), output_field=DurationField())).filter(type__in=("Bannissement illimité", "Ban définitif"))
abscisses = {
    "depuis la création du site": lambda x: x
} | {
    f"en {année}": lambda x, année=année: x.filter(user__date_joined__year=année) for année in range(2014, 2025)
}
ordonnées = {
    "Bannissements permanents": lambda x: x,
    "Bannissements permanents pour spam[^spam]": lambda x: x.filter(note__icontains="spam"),
    "Bannissements permanents pour spam[^spam] (moins de 7 jours après l'inscription)": lambda x: x.filter(note__icontains="spam").filter(depuis_inscription__lte=timedelta(days=7)),
    "Bannissements permanents pour spam[^spam] (moins de 1 jour après l'inscription)": lambda x: x.filter(note__icontains="spam").filter(depuis_inscription__lte=timedelta(days=1)),
    "Bannissements permanents pour spam[^spam] (moins de 1 heure après l'inscription)": lambda x: x.filter(note__icontains="spam").filter(depuis_inscription__lte=timedelta(hours=1)),
}
coin = "Bannissements de comptes créés..."
titre = "Analyse des bannissements permanents"

print_table(base, abscisses, ordonnées, coin, titre)

print_to_file("\n[^spam]: Je n'ai gardé ici que les bannissements dont l'explication donnée par le modérateur contient le mot 'spam'.\n")

### Analyse des signalements

base = Alert.objects
abscisses = {
    "depuis la création du site": lambda x: x
} | {
    f"en {année}": lambda x, année=année: x.filter(pubdate__year=année) for année in range(2016, 2025)
}
ordonnées = {
    "Signalements": lambda x: x,
    "Signalements de profils": lambda x: x.filter(scope="PROFILE"),
    "Signalements de messages sur le forum": lambda x: x.filter(scope="FORUM"),
    "Signalements de contenus": lambda x: x.filter(scope="CONTENT"),
    "Signalements de commentaires": lambda x: x.filter(scope__in=("TUTORIAL", "ARTICLE", "OPINION")),
}
coin = "Signalements émis..."
titre = "Analyse des signalements"

print_table(base, abscisses, ordonnées, coin, titre)

## Signalements par l'antispam des biographies depuis sa mise en place en juin 2020

base = Alert.objects.filter(scope="PROFILE")
abscisses = {
    "depuis la création du site": lambda x: x
} | {
    f"en {année}": lambda x, année=année: x.filter(pubdate__year=année) for année in range(2019, 2025)
}
ordonnées = {
    "Signalements de profils": lambda x: x,
    "Signalements de profils par l'antispam des biographies": lambda x: x.filter(author=antispam_user),
    "Signalements de profils par l'antispam des biographies suivi d'un bannissement": lambda x: x.filter(author=antispam_user).filter(profile__can_read=False).filter(profile__end_ban_read=None),
}
coin = "Signalements émis..."
titre = "Analyse des signalements émis par l'antispam des biographiques"

print_table(base, abscisses, ordonnées, coin, titre)

print_to_file("\n[[information]]\n| L'antispam des biographies a été mis en place en juin 2020 mais le signalement des biographies était effectué par message privé à un groupe de modérateurs. Ce n'est que depuis janvier 2022 que l'antispam utilise la fonction 'Signaler' des profils.")

3 commentaires

Ça fait quand même beaucoup de bande passante et de temps de modération en cumulé, tout ça ! Merci pour cet article et les stats @Situphen !

En tout cas content de voir l’efficacité (et de pouvoir en bénéficier en tant que modo) du robot de signalement ! :)

Peut-être faut-il développer quelques outils pour simplifier la modération (blocage d’IP par exemple, ou utilisation d’une liste noire collaborative), surtout quand on a des vagues à nettoyer (par exemple les comptes qui créent plusieurs topics en quelques minutes, ou les commentaires d’articles/billets qui ont accumulé plusieurs pages de spam SEO).

On se trouverait pas un marabout pour s’en charger ? :D

Bonjour,

Merci pour cette intéressante analyse. J’avais bien remarqué plus souvent du spam ces quelques dernières années et instinctivement je pensais bien que c’était en augmentation massive, un peu partout et pas uniquement sur ZDS, mais je n’imaginais pas que la proportion montait jusqu’à 25%. C’est énorme !

C’est là qu’on voit à quel point les bots sont malheureusement en train de pourrir le web, et ce n’est pas près de s’arranger avec l’IA…

Ca me donne envie de faire ce genre de stats sur mon site à moi, avec un nombre de comptes du même ordre de grandeur (25000 en 14 ans). J’ai pas d’anti-spam automatisé, j’ai mis en place des moyens simples et plus traditionnels, et au-delà d’avoir l’impression que ça marche, je n’ai jamais vraiment vérifié avec des chiffres.

+3 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte