Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Кібернетична вікі. Епізод II. Атака ботів

with 14 comments

Не так давно
на одному
сервері кібцентру…

В Кібернетичній вікі
неспокійно. Більше сотні
користувачів демонструють
наміри закидати її спамом.

Рух спамерів очолюваний
загадковим невідомо ким
(чи взагалі ніким не очолюваний),
перешкоджає малочисельним кіберджедаям
зберігати чистоту й порядок на сайті.

Адміністрато bunyk повертається в КібВікі
щоб зайнятись принциповим питанням: створенням
бота для допомоги джедаям в малоуспішній боротьбі…

Пафосні титри подивились – переходим до банального сюжету про те як добро перемогло зло. 🙂 Зі мною була нова сила (Python 3), і розуміння того що об’єктно-орієнтоване програмування призначене для зменшення кількості подібних параметрів в різних методах. І знання PEP8 яке дозволяє писати код на 8 та більше балів за Пайлінтом.

До того дії всіх ботів я відкидав вручну, слідкуючи за вікі через RSS. Коли їх було 1-2 на день це ще можна було терпіти. Але коли вони повалили десятками я на деякий час забив.

Я вирішив не морочити собі голову з PywikipediaБотом, для роботи якого на cybwiki ще треба створювати окремий файл конфігурації, а змайструвати свого. Свого писати набагато приємніше ніж лазити по сотнях файлів чужого. Крім того, мені дуже соромно за старий bunykwikibot, бо той код – блювотний. Зрозуміло що рік тому я цього не міг бачити. Тому маючи ще один день відпустки який залишився з проходження практики вирішив використати цей шанс щоб виправити ситуацію.

Знайомтесь – bunykwikibot2. Поки що різноманітних запитів до вікі в нього менше. Але зате він вміє логінитись і писати. І з ним приємно працювати.

Покажу на прикладі сьогоднішнього бою проти спамерів (ввесь код):

#!/usr/bin/python3

Ага. Рухаємось вперед. Бо якщо не ми, то хто?

from api import Wiki

Простіше простого. І не треба завантажувати штук п’ять функцій!

def hunt_bots():
    wiki = Wiki('http://cybportal.univ.kiev.ua/w/api.php')
    wiki.session_file('bunyk_on_cybwiki.session')

Це в нашого скрипта головна функція. При запуску створює новий клієнт wiki, для API за заданою адресою. Другий рядочок каже що дані сесії (куки і ще дещо) будуть завантажуватись з вказаного файлу. А якщо їх там нема – попросити в користувача залогінитись і записати туди дані сесії.

    def marked_bot(user):
        userpage = user.userpage().read() or ''
        return '{{Spambot}}' in userpage

Як розрізнити спам і не спам? Пол Грем написав статтю про Баєсівський класифікатор, а я як останній неуч її все ще не читав. Тому вирішив просто позначити всіх ботів вручну, шаблончиком {{Spambot}}. Функція вище отримує текст сторінки користувача, і дивиться чи там не написано що користувач – бот.

Зрозуміло бота ще треба позначити. Цим займається наступна функція:

    def shoot_bot(bot):
        bot.userpage().write('{{Spambot}}', 'Попався!')

Перший її рядок замінює текст сторінки бота позначкою про те що він бот, супроводжуючи цю дію бойовим криком “Попався!”.

        for contrib in bot.contributions():
            spam_page = wiki.page(contrib['title'])
            only_bots = True
            for user in spam_page.contributors():
                if not marked_bot(user):
                    only_bots = False
                    break
            if only_bots:
                spam_page.delete('Спам.')

Далі по черзі розглядаються всі сторінки які бот редагував. І якщо єдиними редакторами цих сторінок були вже позначені боти – сторінки теж видаляються.

        bot.block('Die spammers, die!')

Після цього бот блокується з іншим грізним криком.

Але основна частина скрипта – визначення хто бот, а хто ні:

    for user in wiki.all_users:
        userpage = user.userpage()
        page_text = userpage.read()
        if page_text:
            if '{{Spambot}}' in page_text:
                print(user.name, '- ботяра')
                continue
            if '{{Approved}}' in page_text:
                print(user.name, '- чесний')
                continue
            print(page_text)
        else:
            print('Сторінка користувача порожня')
        edits = user.edit_count()
        print(userpage.title, 'Редагувань: %d' % edits)

Я розглядав кожного користувача. Якщо він вже позначений – виводив повідомлення і брав наступного. Якщо ж ні – виводив текст його сторінки користувача, логін і кількість редагувань.

        if edits < 3:
            verdict = True
        else:
            verdict = ask_y_n('Це бот, як думаєте?'
                '(y/n або порожній рядок якщо не знаєте)'
            )

Спочатку кожну справу я розглядав вручну. Потім до мене якось дійшло що кожен бот залогінювався і робив не більше двох редагувань. Видно вони на більше не розраховані бо їх банять і доводиться реєструвати нові аккаунти. Правда через це мало не “постраждав” Номіровський тому що статтю про себе він редагував переважно анонімно, але я все виправив руками.

        if verdict == '':
            continue
        elif verdict:
            shoot_bot(user)
        else:
            userpage.append(
                '{{Approved}}',
                'Підтвердження того що власник сторінки - не бот.'
            )

Ну і коли сторону користувача визначено, він або розстрілювався, або позначався як наш. Якщо не визначено – пропускався.

Ну після довгої підготовки бій був коротким:
Робота бота

Результати: заблоковано 114 ботів. 40 нормальних користувачів підтверджено.

Тепер напевне пора думати що робити з наступними навалами? Банити всіх хто не поставить на свою сторінку відповідний шаблон, а анонімів за географічною ознакою? Чи таки вчити баєсівський класифікатор розрізняти дифи? Побачимо.

Advertisements

Written by bunyk

Березень 27, 2012 at 23:08

Оприлюднено в Кодерство, Павутина

Tagged with , ,

Відповідей: 14

Subscribe to comments with RSS.

  1. хм. http://cybportal.univ.kiev.ua/wiki/NumPy плашка перенаправляє в нікуди. Також бот ставив плашку?

    danbstt

    Березень 28, 2012 at 00:24

    • Плашку ставив я, посилання – ворожий бот. Я ж пам’ятав що там аноніми теж були скаженими, але з того часу сплило багато історії редагувань.

      Думаєш варто навчити автоматичний класифікатор?

      bunyk

      Березень 28, 2012 at 00:32

      • звісно варто! Це буде дуже круте використання на практиці класифікатора!

        danbstt

        Березень 28, 2012 at 08:43

    • Ті тупі боти такі тупі що навіть в utf-8 не пишуть. Але зарази швидко повернулись.

      bunyk

      Березень 28, 2012 at 00:35

  2. Сюди http://www.mediawiki.org/wiki/Anti-spam_features ти, звісно ж, вже дивився?

    Max Ulidtko

    Березень 28, 2012 at 15:05

    • Не дивився, дякую. Ти ж, до речі, такий самий адмін. Можеш щось з того застосувати?

      bunyk

      Березень 28, 2012 at 17:13

      • Нє, я на то недостатньо змотивований. Простіше кажучи, ліньки.

        Max Ulidtko

        Березень 28, 2012 at 19:46

        • Я так хотів натякнути що там всі способи потребують редагування PHP, а я цього зробити не можу, і не тому що маю на нього алергію, а просто не можу. Ти здається теж. 🙂

          bunyk

          Березень 28, 2012 at 20:00

        • А мотивація то теж цікава штука. Я он місяць терпів те що на кібвікі висить вакансія знятись в гей порно. Потім знайшов час, і таки гарно повеселився.

          Хто в тебе, до речі, науковий керівник, і взагалі як диплом? Я якось думав зв’язатись з Таранухою на тему комп’ютерної лінгвістики, але не знайшов його контактів…

          bunyk

          Березень 28, 2012 at 20:03

  3. диплом печально 😦

    Тарануху в якості керівника не раджу, підійди до краще до Марченка.

    Max Ulidtko

    Березень 28, 2012 at 21:07

    • Блін, знову не влучив :\

      Max Ulidtko

      Березень 28, 2012 at 21:13

      • Та тут не так багато людей щоб можна було загубити дерево діалогу.

        bunyk

        Березень 28, 2012 at 21:21

    • По подібній темі чи взагалі? Мені треба керівника до якого не потрібно підходити, а можна співпрацювати дистанційно.

      bunyk

      Березень 28, 2012 at 21:23

  4. […] я себе тоді коли щось зробив, розібрався, чи навчився. Зрозуміло що таке триває […]


Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: