Avril 2018. J'avais 14 ans. Mes amis et moi avons joué au quiz en ligne alors très populaire «Clover» de VKontakte. L'un de nous (généralement moi) était toujours derrière un ordinateur portable pour essayer de rechercher rapidement les questions sur Google et de parcourir les résultats de recherche pour trouver la bonne réponse. Mais soudain, j'ai réalisé que je faisais la même chose à chaque fois, et j'ai décidé d'essayer de l'écrire en Python 3, que je connaissais alors partiellement.
Étape 0. Que se passe-t-il ici?
Pour commencer, je vais rafraîchir dans votre mémoire la mécanique de "Trèfle".
Le jeu pour tout le monde commence en même temps - à 13h00 et à 20h00, heure de Moscou. Pour jouer, vous devez entrer dans l'application à ce moment et vous connecter à la diffusion en direct. Le jeu dure 15 minutes, pendant lesquelles les questions sont envoyées aux participants par téléphone
en même temps . La réponse est
10 secondes. Ensuite, la bonne réponse est annoncée. Tous ceux qui ont deviné vont plus loin. Il y a 12 questions au total et si vous répondez à toutes, vous recevrez un prix en argent.

Il s'avère que notre tâche consiste à saisir instantanément de nouvelles questions à partir du serveur Clover, à les traiter via un moteur de recherche et à déterminer la bonne réponse en fonction des résultats de la recherche. Il a été décidé de publier la réponse dans un bot de télégramme afin que les notifications de celui-ci apparaissent sur le téléphone pendant le jeu. Et tout cela est souhaitable en quelques secondes, car le temps de réponse est très limité. Si vous voulez voir comment un code assez simple, mais fonctionnel (et en regardant celui-ci sera utile pour les débutants) nous a aidé à battre Clover - bienvenue dans la coupe.
Étape 1. Obtenez des questions du serveur
Au début, cela a semblé l'étape la plus difficile. J'ai déjà pris une profonde inspiration et j'étais prêt à grimper dans la nature comme la vision par ordinateur, intercepter le trafic ou décompiler l'application ... Quand soudain une surprise m'attendait - Clover a une API ouverte! Cela n'est documenté nulle part, mais si pendant le jeu, dès que tous les joueurs ont posé une question, faites une demande sur api.vk.com, alors en réponse, nous obtiendrons la question posée et les options de réponse dans JSON:

https://api.vk.com/method/execute.getLastQuestion?v=5.5&access_token=VK_USER_TOKEN
En tant que jeton d'accès, il est nécessaire de transférer le jeton d'API de tout utilisateur VKontakte, mais il est important qu'il ait été initialement émis spécifiquement pour Clover. Son app_id est 6334949.
Étape 2. Nous traitons le problème via un moteur de recherche
Il y avait deux options: utiliser l'API officielle du moteur de recherche ou ajouter des arguments de recherche directement dans la barre d'adresse et analyser les résultats. Au début, j'ai essayé le second, mais non seulement j'ai parfois attrapé du captcha, j'ai également perdu beaucoup de temps, car les pages se chargent en moyenne en 2 secondes. Et je vous rappelle qu'il est conseillé pour nous de respecter ces deux secondes. Eh bien et l'essentiel - je n'ai pas reçu de texte volumineux et structuré des moteurs de recherche sur le sujet nécessaire, car seuls de petits morceaux du matériel nécessaire, appelés
extraits, sont accrochés sur la page de recherche:

J'ai donc commencé à chercher une API. Google ne convenait pas - leurs solutions étaient très limitées et renvoyaient très peu de données.
Yandex.XML s'est avéré être le plus généreux - il vous permet d'envoyer 10 000 demandes par jour, pas plus de 5 par seconde, et renvoie des données très rapidement. La demande est facultativement le nombre de pages (jusqu'à 100) et le nombre de passages - valeurs spéciales qui sont utilisées pour former des extraits. Nous obtenons les données en XML. Cependant, ce sont tous les mêmes extraits.
Afin que vous puissiez vous familiariser et jouer avec ce que Yandex retourne, voici un exemple de réponse à la question «Quel est le nom de l'antagoniste principal de la série vidéo« The Legend of Zelda? »:
Yandex. Conduisez .
J'ai eu de la chance, et il s'est avéré qu'en pypi, un module de
recherche yandex distinct existe déjà pour cela. Et donc, j'ai essayé d'obtenir la question du serveur, de la trouver dans Yandex, de faire un gros texte à partir d'extraits et de le diviser en phrases:
import requests as req import yandex_search import json apiurl = "https://api.vk.com/method/execute.getLastQuestion?access_token=VK_USER_TOKEN&v=5.5" clever_response = (json.loads(req.get(apiurl).content))["response"]
Étape 3. Recherche de réponses
Initialement, la tâche de reconnaître avec précision la réponse selon des extraits me semblait irréaliste (je vous rappelle qu'au moment de la rédaction du code, j'étais un débutant absolu). Par conséquent, j'ai décidé de simplifier d'abord la tâche que nous avons effectuée avec une recherche manuelle.
Qu'est-ce que mes amis et moi avons fait en insérant notre question dans un moteur de recherche? Ils ont commencé à regarder rapidement à travers les yeux pour trouver des réponses dans les résultats. Quel est le problème avec cette approche? En
plusieurs lettres, il y a un grand nombre de propositions inutiles, ne contenant pas d'informations sur les réponses. Chercher avec mes yeux prenait parfois beaucoup de temps. Par conséquent, la première chose que j'ai décidé de faire a été de sélectionner toutes les phrases avec une mention de l'une des réponses et de les afficher afin que nous puissions rechercher la réponse dans un très petit texte qui contient avec précision les informations dont nous avons besoin.
hint = []
Il semblerait qu'obtenir les bonnes offres, les lire et répondre correctement. Mais que se passe-t-il si nous n'avons pas trouvé une seule phrase? Dans ce cas, j'ai décidé de rogner les mots pour ne pas les rater s'ils sont dans un autre cas. Et aussi pour capturer ceux qui sont formés à partir de la source. En bref, je viens de couper leur fin en deux caractères:
if len(hint) == 0: def cut(string): if len(string) > 2: return string[0:-2] else: return string short_ans1, short_ans2, short_ans3 = cut(ans1), cut(ans2), cut(ans3) for pred in itemslist:
Mais même après un tel filet de sécurité, il y avait encore des cas où l'indice restait vide, simplement parce que les résultats ne touchaient pas toujours les réponses. Dites, à la question
"Lequel de ces écrivains a une histoire, nommée comme la chanson du groupe Bi 2?" aucune réponse exacte ne peut être trouvée. Dans ce cas, j'ai recouru à l'approche inverse - je me suis renseigné sur les réponses et j'ai déduit l'option en fonction de la fréquence à laquelle les mots de la question sont mentionnés dans les résultats.
if len(hint) == 0: questionlist = question.split(" ") blacklist = ["", "", '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] for w in questionlist: if w in blacklist: questionlist.remove(w) yandex_ans1 = yandexfind(ans1) yandex_ans2 = yandexfind(ans2) yandex_ans3 = yandexfind(ans3)
À ce stade, le script a acquis des fonctionnalités de base. Et maintenant, juste une semaine et demie après la sortie de Clover, nous sommes assis et jouons déjà avec un tel «tricheur» autodidacte. Vous auriez dû voir nos visages avec un ami lorsque nous avons
gagné le jeu pour la première
fois en lisant les suggestions sur la ligne de commande comme par magie!
Étape 4. Affichez des réponses claires
Mais bientôt ce format est fatigué. Tout d'abord, vous deviez vous asseoir avec un ordinateur portable à chaque match. Deuxièmement, des amis se sont demandé le script, et je suis fatigué d'expliquer à tout le monde comment insérer son jeton VKontakte, comment configurer Yandex.XML (il est lié à IP, c'est-à-dire qu'il fallait créer un compte pour chaque utilisateur du script) et comment installer python sur l'ordinateur.
Ce serait beaucoup mieux si les réponses apparaissent dans les notifications push sur le téléphone pendant le jeu! Je viens de regarder en haut de l'écran et j'ai répondu comme cela est écrit dans la notification push! Et vous pouvez organiser cela pour tout le monde si vous créez votre chaîne de télégramme pour le script! Magnifique!
Mais afficher simplement les mêmes phrases dans les télégrammes n'est pas une option. Les lire à partir de votre téléphone est extrêmement gênant. Par conséquent, j'ai dû apprendre le script moi-même pour comprendre quelle réponse est correcte.
Nous importons
telebot et changeons toutes
les fonctions
print () en
send_tg () et
notsure () , que nous utiliserons dans la dernière méthode, car elle manque un peu plus souvent que les autres:
def send_tg(ans): bot.send_message("@autoclever", str(ans).capitalize()) print(str(ans)) return def notsure(ans): send_tg(ans.capitalize() + ". !") hint.append("WE TRIED!")
Et à ce moment-là, j'ai réalisé que les extraits étaient bien meilleurs que les longs textes! Parce que le moteur de recherche essaie très fort de
répondre à notre demande, et pas seulement de trouver des correspondances en mots. Et il réussit - les extraits contenaient souvent les bonnes réponses que les mauvaises, c'est-à-dire qu'il n'était pas nécessaire d'analyser le texte. Et moi, en fait, je ne savais pas comment.
Nous sommes donc simples à compter la mention des mots dans les résultats:
anscounts = { ans1: 0, ans2: 0, ans3: 0 } for s in hint: for a in [ans1, ans2, ans3]: anscounts[a] += s.count(a) right = (max(anscounts, key=anscounts.get)) send_tg(right)
Que s'est-il passé en conséquence:

Destin supplémentaire
En toute honnêteté, je dois dire que je n'ai pas réussi dans la machine à mort. En moyenne, le bot n'a répondu correctement qu'à 9 à 10 des 12 questions. C'est compréhensible, car il y en a eu des difficiles qui n'ont pas succombé à l'analyse de la recherche Yandex. Moi et mes amis, nous sommes fatigués de constamment survoler quelques questions et d'attendre un jeu réussi, dans lequel le bot va enfin tout répondre correctement. Un miracle ne s'est pas produit, je ne voulais plus vraiment modifier le script, puis, ayant cessé d'espérer une victoire facile, nous avons abandonné le jeu.
Au fil du temps, mon idée a commencé à se glisser dans la tête d'autres jeunes développeurs. Au coucher du soleil de 2018, il y avait au moins 10 robots et sites affichant leurs suppositions sur les problèmes de Clover. La tâche n'est pas si difficile. Mais ce qui est surprenant, aucun d'entre eux n'a jamais franchi la barre des 9-10 questions par match, et plus tard tous sont tombés à 7-8, comme mon bot. Apparemment, les compilateurs des questions ont indiqué clairement comment les composer afin que le travail des moteurs de recherche ne soit pas pertinent.
Malheureusement, le bot ne peut plus être finalisé, car le 31 décembre, Clover a passé la dernière diffusion, et je n'ai pas eu de questions. Cependant, ce fut une grande expérience pour un programmeur débutant. Et il y aurait sûrement un grand défi pour le plus avancé - imaginez le duo word2vec et text2vec, les demandes asynchrones à Yandex, Google et Wikipedia en même temps, un classificateur avancé de questions et un algorithme pour reformuler la question en cas d'échec ... Eh! Peut-être, pour de telles opportunités, j'ai adoré ce jeu plus que pour le gameplay lui-même.