April 2018. Saya berusia 14 tahun. Teman saya dan saya bermain di kuis online yang sangat populer "Clover" dari VKontakte. Salah satu dari kami (biasanya saya) selalu di belakang laptop untuk mencoba dengan cepat pertanyaan google dan melihat melalui hasil pencarian untuk jawaban yang benar. Tapi tiba-tiba saya menyadari bahwa saya melakukan hal yang sama setiap waktu, dan memutuskan untuk mencoba menulisnya dengan Python 3, yang sebagian saya kenal saat itu.
Langkah 0. Apa yang terjadi di sini?
Untuk memulainya, saya akan menyegarkan kembali ingatan Anda mekanisme "Semanggi".
Permainan untuk semua orang dimulai pada waktu yang sama - pukul 13:00 dan 20:00 waktu Moskow. Untuk bermain, Anda harus masuk ke aplikasi saat ini dan terhubung ke siaran langsung. Permainan ini berlangsung selama 15 menit, di mana pertanyaan dikirimkan kepada peserta di telepon
pada saat yang sama . Jawabannya adalah
10 detik. Kemudian jawaban yang benar diumumkan. Semua yang menebak melangkah lebih jauh. Ada 12 pertanyaan secara total, dan jika Anda menjawab semua, Anda akan menerima hadiah uang tunai.

Ternyata tugas kami adalah menangkap langsung pertanyaan baru dari server Clover, memprosesnya melalui mesin pencari, dan menentukan jawaban yang benar berdasarkan hasil pencarian. Diputuskan untuk mengeluarkan jawaban dalam bot telegram sehingga pemberitahuan darinya akan muncul di ponsel selama pertandingan. Dan semua ini diinginkan dalam beberapa detik, karena waktu respons sangat terbatas. Jika Anda ingin melihat bagaimana kode yang cukup sederhana, tetapi bekerja (dan melihat yang ini akan berguna bagi pemula) membantu kami mengalahkan Clover - selamat datang di cut.
Langkah 1. Dapatkan pertanyaan dari server
Pada awalnya itu tampaknya tahap yang paling sulit. Saya sudah mengambil napas dalam-dalam dan siap untuk naik ke alam liar seperti visi komputer, mencegat lalu lintas atau mendekompilasi aplikasi ... Ketika tiba-tiba sebuah kejutan menunggu saya - Clover memiliki API terbuka! Itu tidak didokumentasikan di mana pun, tetapi jika selama pertandingan, segera setelah semua pemain ditanya pertanyaan, buat permintaan di api.vk.com, maka sebagai tanggapan kami akan mendapatkan pertanyaan yang diajukan dan pilihan jawaban di JSON:

https://api.vk.com/method/execute.getLastQuestion?v=5.5&access_token=VK_USER_TOKEN
Sebagai access_token, perlu untuk mentransfer token API dari setiap pengguna VKontakte, tetapi penting bahwa itu pada awalnya dikeluarkan khusus untuk Clover. App_id-nya adalah 6334949.
Langkah 2. Kami memproses masalah ini melalui mesin pencari
Ada dua opsi: gunakan API mesin pencari resmi atau tambahkan argumen pencarian langsung ke bilah alamat, dan pars hasilnya. Pada awalnya saya mencoba yang kedua, tetapi saya tidak hanya menangkap captcha, saya juga kehilangan banyak waktu, karena halaman dimuat rata-rata dalam 2 detik. Dan saya mengingatkan Anda bahwa disarankan untuk bertemu dua detik ini. Baik dan yang paling penting, saya tidak mendapatkan teks yang besar dan terstruktur dari mesin pencari pada topik yang diperlukan, karena hanya potongan-potongan kecil dari bahan yang diperlukan, yang disebut
snippet, bertahan di halaman pencarian:

Jadi saya mulai mencari API. Google tidak cocok - solusi mereka sangat terbatas dan mengembalikan data yang sangat sedikit.
Yandex.XML ternyata yang paling murah hati - memungkinkan Anda mengirim 10.000 permintaan per hari, tidak lebih dari 5 per detik, dan mengembalikan data dengan sangat cepat. Permintaan untuk itu secara opsional adalah jumlah halaman (hingga 100) dan jumlah bagian - nilai khusus yang digunakan untuk membentuk snippet. Kami mendapatkan data dalam XML. Namun, ini semua cuplikan yang sama.
Agar Anda dapat membiasakan diri dan bermain dengan apa yang dikembalikan Yandex, berikut adalah contoh jawaban untuk pertanyaan "Apa nama antagonis utama dalam seri video" The Legend of Zelda? ":
Yandex. Berkendara .
Saya beruntung, dan ternyata di pypi, modul
pencarian yandex terpisah sudah ada untuk ini. Maka, saya mencoba mendapatkan pertanyaan dari server, menemukannya di Yandex, membuat satu teks besar dari cuplikan dan memecahnya menjadi kalimat:
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"]
Langkah 3. Mencari jawaban
Pada awalnya, tugas mengenali jawaban secara akurat berdasarkan cuplikan tampaknya tidak realistis bagi saya (saya mengingatkan Anda bahwa pada saat menulis kode, saya adalah pemula mutlak). Karena itu, saya memutuskan untuk menyederhanakan tugas yang kami lakukan dengan pencarian manual.
Apa yang saya dan teman saya lakukan ketika mengarahkan pertanyaan kami ke mesin pencari? Mereka mulai cepat melihat melalui mata untuk jawaban dalam hasil. Apa masalah dengan pendekatan ini? Dalam
banyak huruf, ada sejumlah besar yang tidak perlu, tidak mengandung informasi tentang jawaban, proposal. Mencari dengan mata saya terkadang membutuhkan waktu lama. Oleh karena itu, hal pertama yang saya putuskan untuk lakukan adalah memilih semua kalimat dengan menyebutkan salah satu jawaban dan menampilkannya sehingga kami akan mencari jawabannya dalam teks yang sangat kecil yang secara akurat berisi informasi yang kami butuhkan.
hint = []
Tampaknya mendapatkan tawaran yang tepat, membacanya dan menjawab dengan benar. Tetapi bagaimana jika kita tidak menemukan satu kalimat pun? Dalam hal ini, saya memutuskan untuk memotong kata-kata agar tidak ketinggalan jika ada dalam kasus lain. Dan juga untuk menangkap yang terbentuk dari sumbernya. Singkatnya, saya baru saja memotong akhir mereka menjadi dua karakter:
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:
Tetapi bahkan setelah jaring pengaman seperti itu, masih ada kasus ketika petunjuk tetap kosong, hanya karena hasilnya tidak selalu menyentuh pada jawaban. Katakan, pada pertanyaan,
"Manakah dari penulis ini yang memiliki kisah, yang dinamai seperti lagu dari grup Bi 2?" tidak ada jawaban pasti yang dapat ditemukan. Dalam hal ini, saya menggunakan pendekatan yang berlawanan - saya bertanya tentang jawaban dan menyimpulkan opsi berdasarkan seberapa sering kata-kata dari pertanyaan tersebut disebutkan dalam hasil.
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)
Pada titik ini, skrip mendapatkan fungsionalitas dasar. Dan sekarang, hanya satu setengah minggu setelah rilis Clover, kami duduk dan sudah bermain dengan "cheat" buatan sendiri. Anda seharusnya melihat wajah kami bersama seorang teman ketika kami pertama kali
memenangkan permainan dengan membaca saran di baris perintah seolah-olah dengan sihir!
Langkah 4. Tampilkan jawaban yang jelas
Namun format ini segera lelah. Pertama, Anda harus duduk dengan laptop setiap pertandingan. Kedua, teman-teman saya meminta skrip, dan saya bosan menjelaskan kepada semua orang cara memasukkan token VKontakte mereka, cara mengkonfigurasi Yandex.XML (terkait dengan IP, artinya, perlu membuat akun untuk setiap pengguna skrip) dan cara memasang python di komputer.
Akan jauh lebih baik jika jawaban muncul dalam pemberitahuan push di ponsel tepat selama pertandingan! Hanya melihat bagian atas layar dan menjawab seperti yang tertulis di pemberitahuan push! Dan Anda dapat mengatur ini untuk semua orang jika Anda membuat saluran telegram Anda untuk skrip! Luar biasa!
Tetapi hanya menampilkan kalimat yang sama di telegram bukanlah suatu pilihan. Membacanya dari ponsel Anda sangat merepotkan. Karena itu, saya harus mempelajari naskah sendiri untuk memahami jawaban mana yang benar.
Kami mengimpor
telebot dan mengubah semua fungsi
cetak () menjadi
send_tg () dan
notsure () , yang akan kami gunakan dalam metode terakhir, karena ia sedikit lebih sering hilang daripada yang lain:
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!")
Dan pada saat itu, saya menyadari bahwa cuplikan jauh lebih baik daripada teks panjang! Karena mesin pencari berusaha sangat keras untuk
memberikan jawaban atas permintaan kami, dan tidak hanya menemukan kecocokan dalam kata-kata. Dan dia berhasil - potongan sering berisi jawaban yang benar daripada yang salah, yaitu, tidak perlu menganalisis teks. Dan saya, pada kenyataannya, tidak tahu caranya.
Jadi kita sederhana untuk menghitung penyebutan kata-kata dalam hasil:
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)
Apa yang terjadi sebagai hasilnya:

Nasib selanjutnya
Dalam keadilan, saya harus mengatakan bahwa saya tidak berhasil dalam mesin kematian. Rata-rata, bot menjawab dengan benar hanya 9-10 dari 12 pertanyaan. Dapat dimengerti, karena ada orang-orang rumit yang tidak menyerah pada penguraian pencarian Yandex. Saya, dan teman-teman saya, bosan terus-menerus terbang melewati beberapa pertanyaan dan menunggu permainan yang sukses, di mana bot akhirnya akan menjawab semuanya dengan benar. Sebuah keajaiban tidak terjadi, saya tidak benar-benar ingin memodifikasi naskah lagi, dan kemudian, setelah berhenti berharap untuk kemenangan yang mudah, kami meninggalkan permainan.
Seiring waktu, ide saya mulai merayap ke kepala pengembang muda lainnya. Menjelang matahari terbenam tahun 2018, setidaknya ada 10 bot dan situs yang menampilkan tebakan mereka tentang masalah di Clover. Tugasnya tidak begitu sulit. Tapi yang mengejutkan, tidak ada satu pun dari mereka yang pernah melewati 9-10 pertanyaan per game, dan kemudian semuanya turun menjadi 7-8 sama sekali, seperti bot saya. Rupanya, para penyusun pertanyaan memperjelas bagaimana menyusun pertanyaan sehingga pekerjaan mesin pencari tidak relevan.
Sayangnya, bot tidak dapat diselesaikan lagi, karena pada tanggal 31 Desember Clover menghabiskan siaran terakhir, dan saya tidak memiliki pertanyaan. Namun, itu adalah pengalaman hebat bagi seorang programmer pemula. Dan tentunya akan ada tantangan besar untuk yang maju - bayangkan saja duo word2vec dan text2vec, permintaan asinkron ke Yandex, Google dan Wikipedia pada saat yang sama, pengelompokan pertanyaan tingkat lanjut dan algoritme untuk merumuskan kembali pertanyaan jika terjadi kegagalan ... Eh! Mungkin, untuk kesempatan seperti itu saya lebih menyukai game ini daripada gameplaynya.