Mungkin, di setiap kota di Belarus di mana terdapat troli, ada grup VK atau obrolan di Telegram di mana orang melacak lokasi pengontrol. Hal ini terutama dilakukan agar tidak membayar untuk perjalanan dan perjalanan gratis, meskipun deskripsi grup hampir selalu berisi catatan tambahan “Bayar untuk perjalanan”.
Dalam VC, biasanya terlihat seperti ini:

Komentar khas terlihat seperti ini:

Strukturnya sangat sederhana. Dalam komentar ada nama-nama perhentian di mana pengendali saat ini diperhatikan, ada juga arah mereka berdiri:

Komentar, sebagai hasilnya, adalah objek dengan stop, waktu dan tanggal, serta id unik yang dengannya kami dapat mengidentifikasinya. Dengan ini, Anda dapat menghitung lokasi di mana pengendali berada.
Persiapan
Pertama, Anda perlu menentukan target publik, dari mana kami akan menguraikan data. Grup harus memiliki cukup banyak aktivitas dalam komentar, jika tidak, kita berisiko mendapatkan data terlalu sedikit
Dalam kasus saya, ini adalah grup "Control Gomel".
Kami akan mengurai komentar menggunakan API VKontakte resmi untuk Python
Kami mengautentikasi dengan kunci akses pengguna, karena beberapa grup mungkin ditutup, dan akses ke komentar mereka hanya dapat diperoleh jika Anda diterima ke dalam grup.
Setelah itu, Anda dapat mulai mengekstraksi komentar:
Terima komentar
Untuk memulainya, kita mendapatkan posting terakhir yang tersedia di grup untuk menarik komentar melalui vk.wall.getComments, dan menginisialisasi DataFrame, di mana kita akan menyimpan data.
Setiap pos komentar memiliki tulisan "Semoga harimu menyenangkan, bayar ongkosnya, dan jangan terkendali", jadi unduh komentarnya, periksa konten kiriman dan dapatkan serangkaian komentar yang dapat digunakan untuk mengambil data.
Saya mengambil komentar dari posting selama 3 bulan terakhir, mengingat bahwa 1 posting diposting setiap hari (sekarang akhir November, tahun sekolah dimulai pada bulan September, dan pengawas kemungkinan besar mempertimbangkan ini dan mengubah tempat biasa mereka). Pada prinsipnya, tanda-tanda lain dapat diperhitungkan, seperti, misalnya, waktu tahun.
Beberapa komentar tersumbat dengan pesan seperti "Apakah ada orang di Barykin?" Jika Anda melihat komentar seperti itu (tidak perlu), Anda dapat menyorot beberapa tanda:
- Teks berisi kata-kata "bersih", "kiri", "tidak ada" dan sejenisnya
- Kata-kata "katakan padaku", "siapa", "apa", "bagaimana"
- Simbol, seperti emotikon, misalnya
Setelah itu, kita pergi melalui serangkaian komentar dan mengeluarkan id unik, teks, waktu, tanggal dan hari dalam seminggu dari mereka, yang kita masukkan ke dalam DataFrame yang sudah dibuat.
Terima komentarimport re import time import pandas as pd import lp import vk_api import check_correctness def auth(): vk_session = vk_api.VkApi(lp.login, lp.password) vk_session.auth() vk = vk_session.get_api() return vk def getDataFromComments(vk, groupID):
Jadi, kami menerima DataFrame dengan teks komentar, id mereka, hari dalam seminggu, jam dan menit di mana komentar itu ditulis. Kita hanya perlu hari dalam seminggu, jam menulis dan teks. Itu terlihat seperti ini:

Pembersihan data
Sekarang kita perlu menghapus data. Penting untuk menghapus arah dari komentar untuk membuat lebih sedikit kesalahan saat mencari jarak Levenshtein. Kami menemukan ekspresi "ke samping", "pergi", "bagaimana", "dekat", karena biasanya diikuti dengan nama perhentian kedua, dan kami menghapusnya bersama dengan apa yang datang setelahnya, serta mengganti beberapa nama jargon perhentian dengan yang biasa .
Hapus data from fuzzywuzzy import process def clear_commentary(text): """ - """ index = 0 splitted = text.split(" ") for i, s in enumerate(splitted): if len(splitted) == 1: return np.NaN if ((("" in s) or ("" in s) or ( "" in s) or ( "" in s)) and s is not ""): index = i if index is not 0 and index < len(splitted) - 2: for i in range(1, 4): splitted.remove(splitted[index]) string = " ".join(splitted) text = (string.lower()) elif index is not 0: splitted = splitted[:index] string = " ".join(splitted) text = string.lower() else: text = " ".join(splitted).lower() return text def clean_data(data): data.dropna(inplace=True) data["text"] = data["text"].map(lambda s: clear_commentary(s)) data.dropna(inplace=True) print("cleaned") return data
Konversi menggunakan jarak Levenshtein
Kami langsung melanjutkan ke jarak Levenshane. Sedikit bantuan: Levenshtein distance - jumlah operasi minimum untuk memasukkan satu karakter, menghapus satu karakter dan mengganti satu karakter dengan yang lain, diperlukan untuk mengubah satu baris menjadi yang lain.
Kami akan menemukannya menggunakan perpustakaan
fuzzywuzzy . Ini membantu Anda dengan cepat dan mudah menghitung jarak Levenshtein. Untuk mempercepat pekerjaan, penulis perpustakaan juga merekomendasikan menginstal perpustakaan python-Levenshtein.
Untuk mendapatkan pemberhentian dari komentar, kami membutuhkan daftar pemberhentian. Itu diberikan kepada saya oleh pengembang aplikasi GoTrans, Alexander Kozlov.
Daftar itu harus diperluas, menambahkan ada beberapa perhentian yang tidak ada di sana, dan mengubah sebagian nama sehingga mereka lebih baik berada.
Berhentistops = ['supermarket', 'meadow', 'remybtekhnika', 'Leningrad', 'Yaroslavl', 'Polesskaya',
'Yaroslavl', 'timofeenko', '8 Maret,
'Rumah dagang Rechitsky', 'Jalan Rechitsky', 'sirkus', 'department store', 'Chongarskaya',
'chongarka', 'ggu', 'skorina', 'universitas', 'appliance', '1000 hal-hal kecil', 'maya', 'station',
'taman lulusan', 'perdagangan dan ekonomi', 'ulang tahun', 'mikrodistrik 18', 'bandara', 'akan datang',
'gomelgeodezcentr', 'kristal', 'danau lyubenskoye', 'pasar davydovsky', 'davydovka',
'sungai sozh', 'gomeldrev',
'Sevruki', 'gmu No. 1', 'dll. Rechitsky', 'kostum', 'rumah sakit penyakit menular', 'kamp camar',
Volotova, Coral, Gomeltorgmash, Gomelproekt, Vneshgomelstroy, Surat Kabar,
'Kalenikova', 'Eremino', 'penyulingan', 'otomatisasi industri khusus', '2nd School', 'Barykina',
'unit mesin', 'pemuda', 'badan casting', 'ahli kimia', 'golovatsky', 'budenny',
'spu67', '35', 'gagarin', '50 tahun ke pabrik Gomselmash ',' hill ',' pabrik radio ',
'nenek', 'pabrik kaca', 'berangan', 'mesin mulai', 'astronot',
'awal rtsrm', 'bykhovskaya', 'lembaga kementerian situasi darurat', 'dk gomselmash', 'toko', 'rechitsky',
'Sevruks', 'Osovtsy', 'turis', 'pabrik daging', 'Trinitas Suci', 'kota medis', 'Oktober',
'depot minyak', 'gomelloblavtotrans', 'milkavita', 'bakunin', 'zip', 'oma', 'resin',
'pasar konstruksi ksk', 'pembangun jalan', 'lapangan', 'kamenetskaya', 'bolshevik', 'jakubovka',
'Borodina', 'hippo hypermarket', 'pahlawan bawah tanah', '9 Mei,' kastanye ',' prosthetist ',
'stasiun iput', 'komunis internasional', 'perguruan pedagogis musik', 'perusahaan pertanian', 'jalan pintas', 'kemenangan',
'barat', 'mutiara', 'Vladimir', 'kering', 'apotik', 'Ivanova',
'pembuatan mesin', 'birch', '60 tahun ',' insinyur listrik ',' centrolite ',
'klinik onkologis', 'jarak tembak', 'golovintsy', 'karang', 'selatan', 'musim semi',
Efremova, Perbatasan, Belgut, Gomelstroy, Borisenko, Istana Atletik,
'Michurinsky', 'solar', 'gastello', 'militer', 'auto centre', 'plumbing', 'uza',
'perguruan tinggi kedokteran', 'taman kanak-kanak 11', 'Bolshevik', 'anak anjing', 'Davydovsky', 'lautan', 'kemajuan',
'Dobrushskaya', 'putih', 'GSK', 'davydovka', 'peralatan listrik', 'persahabatan',
'70 tahun ',' perbaikan mobil ',' bukit swedia ',' sirkuit ',' saluran air ',' mesin gomel ',
Volotova, Pelopor, RCM, Khimtorg, 2nd Meadow Lane, Bochkina, Baths,
'klinik onkologis', 'kotak', 'Lenin', 'sekolah pertama', 'toko selatan',
'gomelagrotrans', 'penggiling', 'lyubensky', 'kantor pendaftaran militer', 'rumah sakit', 'uza', 'rtsrm',
'lysyukovyh', 'shop iput', 'raton', 'pompa bensin', 'randovsky', 'rumah pertanian', 'chestnut', 'ropovsky',
'Romanovichi', 'Ilyich', 'dayung', 'perusahaan konstruksi', 'menular',
'pabrik gemuk', 'layanan mobil', 'layanan pertanian', 'lengket', 'Nikolskaya',
'pemanen self-propelled', 'tukang batu', 'bahan bangunan', 'mesin perbaikan', 'administrasi',
'Oktober', 'dongeng hutan', 'Tatiana', 'Boris Tsarikov', 'Zharkovsky', 'Zaitseva',
'relokasi', 'Karpovich', 'pabrik pembangunan rumah', 'transportasi listrik kota', 'zlin',
'stadium gomselmash', 'ap 6', 'penggerak hidrolik', 'depo lokomotif', 'pasar mobil osovtsy',
'kehidupan baru', 'Zhukova', 'unit militer', 'sekolah ke-3', 'hutan', 'mercusuar merah',
'regional', 'Davydovskaya', 'Karbysheva', 'satelit dunia', 'pemuda', 'lokomotif stadion',
'solar', 'Ladaservice', 'μR 21', 'Aresa', 'internasionalis', 'Kosareva',
'Bogdanova', 'Gomel iron-concrete', 'μr 20a', 'μr Rechitsky', 'peralatan medis', 'Juraeva',
'perguruan tinggi kerajinan seni', 'es', 'festival dk', 'pusat perbelanjaan',
'Kuibyshevsky', 'festival', 'garasi koop 27', 'teknik seismik', 'milcha', 'rumah sakit tabung',
'ptu179', 'produk kimia', 'pemadam kebakaran', 'rumah sakit', 'depot bus',
'kompleks surat kabar', 'kemenangan', 'klenkovsky', 'berlian', 'perbaikan mesin', 'mkr 19']
Menggunakan .map dan fuzzywuzzy.process.extractOne, kami menemukan pemberhentian dengan jarak Levenshtein minimum dalam daftar, setelah itu kami mengganti teks komentar dengan nama pemberhentian, yang memungkinkan kami mendapatkan dataset dengan nama pemberhentian.
Dataset yang dihasilkan terlihat seperti ini:

Komentar berubah menjadi berhenti def get_category_from_comment(text): """ """ dict = process.extractOne(text.lower(), stops) if dict[1] > 75: text = dict[0] else: text = np.nan print("wait") return text def get_category_dataset(data): """ """ print("remap started. wait") data.text = data.text.map(lambda comment: get_category_from_comment(str(comment))) print("remap ends") data.dropna(inplace=True) data["text"] = data.text.map(lambda s: "" if s=="" else s) data["text"] = data.text.map(lambda s: "" if s=="" else s) data["text"] = data.text.map(lambda s: " " if s=="" else s) data["text"] = data.text.map(lambda s: " " if s=="" else s) return data
Output data
Sekarang kita dapat mengasumsikan di mana pengendali kemungkinan besar berada pada jam yang diberikan.
Kami mencari dalam catatan data yang dihasilkan untuk jam dan hari tertentu dalam seminggu. Misalnya, pada hari Selasa, jam 9 pagi:
<code>data[(data["day_in_week"] == day) & (data["hour"] == hour)]</code>
(ini tidak semua data)Setelah itu, kami menemukan jumlah pemberhentian unik, dan hanya menampilkan pemberhentian, dan jumlah mereka:
df[(df["day_in_week"] == 2) & (df["hour"] == 9)]["text"].value_counts()

Sekarang kita dapat mengatakan bahwa pada jam 9 pagi, pada hari Selasa, pengendali kemungkinan besar akan terlihat di halte Myasokombinat, ul. Lugovaya, BelGUT, TD "Oma".
Kelemahan utama dalam metode ini adalah kurangnya data. Tidak untuk semua hari dan jam ada entri dalam komentar yang diberikan selama jam sibuk, ketika orang menggunakan transportasi umum lebih dari data dalam jam kurang populer, tetapi jika Anda menambahkan data, misalnya, tidak hanya dari komentar satu kelompok, tetapi juga dari grup alternatif, atau obrolan telegram, dengan jumlah entri, semuanya akan menjadi lebih mudah.
Bot dengan VK LongPoll API
Untuk memungkinkan saya menerima data di lokasi pengendali, tergantung pada waktu, dan tanpa terikat ke komputer, saya membuat bot untuk grup di VKontakte yang merespons pesan apa pun dengan mengirimkan jumlah pemberhentian dalam catatan, dengan mempertimbangkan jam dan hari dalam seminggu.
Kode bot from random import randint import vk_api from requests import * from get_stops_from_data import get_stops_by_time def start_bot(data, token): vk_session = vk_api.VkApi(token=token) vk = vk_session.get_api() print("bot started") longPoll = vk.groups.getLongPollServer(group_id=183524419) server, key, ts = longPoll['server'], longPoll['key'], longPoll['ts'] while True:
Kesimpulan
Kualitas hipotesis semacam itu telah diuji oleh saya lebih dari satu kali dalam praktik, dan semuanya bekerja dengan baik. Ternyata pengendali, pada dasarnya, berada di halte yang sama, meskipun perkiraan yang benar-benar benar tidak dapat diberikan, dan probabilitas keberhasilannya tidak 100%. Jarak Levenshtein memiliki lusinan aplikasi yang berbeda, dari mengoreksi kesalahan dalam satu kata, hingga membandingkan gen, kromosom dan protein, tetapi juga memiliki potensi dalam masalah yang diterapkan tersebut.
Semoga harimu menyenangkan, dan bayar ongkosnya.
Semua kode bot dan manipulasi data diterbitkan di
sini .