Популярные в последнее время слухи о блокировке торрент-трекеров (или уже не слухи?) побудили меня написать свой парсер для сайта rutracker.org. В данной статье я опишу опции для скрипта, выходные данные. Также прилагается просмотрщик с возможность поиска по категориям, и база раздач с описаниями от 16.01.2016.



Зачем?


  1. На момент начала работы над скриптом, rutracker еще не выкладывал свою базу.
  2. В данной базе присутствуют описания раздач.
  3. Похожая статья была на хабре в 2013 году, но к сожалению, данная база ни разу не обновилась после публикации, а последнее обновление репозитория было 16.01.2014 года.
  4. Это мое первое большое приложение на python, что позволило познакомиться со множеством интересных возможностей языка, начиная от распараллеливания задач и заканчивая компиляцией бинарника под windows.


Пример запуска скрипта для зеркалирования сайта


python3 ./loader.py --ids 0000001 5160000 --threads 200 --qsize 25 --resume

Описание параметров


Опция Описание
--ids 0000001 0001000 качает раздачи в указанном диапазоне
--ids_file file_with_ids.txt берет номера раздач для скачивания из указанного файла
--ids_ignore old_finish.txt исключает из закачки раздачи, которых нет в указанном файле (например, можно пропустить те номера, которых не было при прошлой закачке)
--random скачивать раздачи в случайном порядке
--threads 100 число потоков для скачивания
--proxy_file proxy.txt файл с socks5 прокси (по умолчанию — proxy.txt)
--login_file login.txt файл с логинами к сайту (по умолчанию — login.txt)
--resume продолжить предыдущую закачку (игнорировать раздачи из файла finished.txt)
--print вместе с опцией resume выведет количество скачанных/не скачанных раздач и завершает работу программы
--folder descriptions указывает название директории, куда будут сохраняться описания раздач (по умолчанию — descr)
--qsize 20 максимальная величина очереди для скачивания (по умолчанию — 30)

Описания вспомогательных текстовых файлов


Формат файла с логинами к сайту


username1 password1
username2 password2

Примечание: Дата изменения раздачи зависит от часового пояса, установленного в профиле.

Формат файла с прокси


127.0.0.1 8080
127.0.0.1 8081

В процессе работы


Номера скачанных или не существующих раздач записываются в файл finished.txt. Лог выводится параллельно в консоль и в файл log.txt. Cookie пишутся в temp_cookies.txt, для сохранения между сессиями.

Описание результата


В файле table.txt сохраняется информация о раздачах (за исключением описаний). Для каждой раздачи сохраняются (разделитель — \t):
  • Идентификатор
  • Название раздачи
  • Размер (в байтах)
  • Количество сидов
  • Количество пиров
  • Хэш
  • Количество скачиваний
  • Дата создания
  • Категория, включая все подкатегории (разделитель – “ | “)

Пример:

4130425 Mark Lutz/Марк Лутц - Изучаем Python, 4-е издание [2011, PDF, RUS] 12799942 390 9 B507A45DA54ED5EED13221B16E2030DF789A235F 46455 28-08-12 11:28 Книги и журналы | Компьютерная литература | Программирование


Описания раздач сохраняются в отдельные файлы в папку descr (или указанную опцией --folder), в поддиректорию по первым трем цифрам номера раздачи.

Например, описание раздачи 04893221 сохранится в descr\048\04893221.

Основные проблемы, которые возникали при создании скрипта


  1. Ограничения сайта на 1 логин и на 1 IP-адрес, в конечном итоге самое простое решение – одновременно использовать IP и логин только в одном потоке.
  2. Модуль multiprocessing для создания потока использует системный вызов fork, который копирует текущий процесс. Соответственно, если сначала читаются все конфиги, строится список на закачку, то процесс кушает более 50 Мб памяти и все потомки получаются такими же тяжелыми. Решение – сначала создать пулл процессов, а только затем читать конфиги.
  3. На разным страницах одна и та же информация о раздаче может быть представлена в немного разных видах в исходном коде. Решение – при появлении ошибок вручную вносил дополнительные варианты в скрипт.
  4. Работа с сетевым стеком, в особенности, если использовать непроверенные прокси-серверы, может давать кучу всевозможных ошибок. При большом количестве ошибок с одного прокси – он блокируется, если страница получена с ошибкой – она добавляется в конец очереди, для повторной загрузки.
  5. Множество всевозможных ошибок при написании многопроцессорного приложения. Наиболее действенным методом отладки стало логгирование всего и вся с различными уровнями отображения.
  6. При создании просмотрщика главной проблемой стал поиск по раздачам. Полнотекстовый поиск в MySQL отказался искать по части слова (только по полному совпадению). Полной перебор слишком долог. Текущий компромисс – список отсортирован по числу сидов, поиск выполняется последовательно, до нахождения заданного количества результатов.


Просмотрщик


Для просмотра сохраненной базы и поиска по раздачам написан просмотрщик с использованием PyQt5. Для работы необходим файл table_sorted.tar.bz2, который содержит текстовый файл table_sorted.txt (table.txt, отсортированный по число сидов). Для конвертации можно использовать данный скрипт.

Также (опционально) можно положить рядом со скриптом директорию descr, в которой будут лежать заархивированные описания раздач. Я паковал этим скриптом.

Пример структуры директорий и архивов:

        descr/000/00000.tar.bz2
        descr/000/00001.tar.bz2
        …
        descr/000/00099.tar.bz2
        descr/001/00100.tar.bz2
        descr/001/00101.tar.bz2
        …
        descr/001/00199.tar.bz2
        …

Внешний вид просмотрщика показан на КДПВ.

Опции для поиска


  1. Минус перед словом для исключения раздач с ним из выдачи.
  2. limit:5 для задания ограничения результатов, после нахождения которых прекращается поиск (по умолчанию – 20).
  3. В правом поле можно ввести слова для поиска в наименовании категории.


Двойной клик по хэшу копирует магнет-ссылку с ним в буфер обмена.

Требования


python3-pyqt5, python3-pyqt5.qtwebkit

Установка


Скрипт для python3.

Скомпилированный бинарник для Windows: Mega.nz (30 Мб) (включая все необходимые библиотеки).

База по состоянию на 16.01.2016


Файл с основной информацией о раздачах, отсортированный по количеству сидов: Mega.nz (118 Мб).

Описания раздач (распаковать в папку с просмотрщиком): Mega.nz (2.06 Гб).

Любая критика по коду приветствуется.

В дальнейшем есть задумка добавить в просмотрщик поддержку libtorrent и получить возможность просматривать содержимое раздач/стримить их в проигрыватель.

Также у меня есть сохраненная база от июня 2014 года (без категорий) и от июля 2015 года (с категориями), если есть пожелания, могу посчитать какую-нибудь статистику по изменениям между этими срезами.

Исходники скриптов выложены на github.

Комментарии (14)


  1. forgotten
    26.01.2016 12:29
    +19

    Один мой друг интересуется, нет ли такого же, но для порнолаба и с сохранением скриншотов?


    1. strayge
      26.01.2016 12:35
      +1

      Нету, подправить скрипт не сильно сложно, но:
      1) Из-за более низкого числа сидеров, раздачи, удаленные с сайта, будут быстрее умирать.
      2) В текущей версии с сайта тянется только исходный код описания, ссылки на внешние хостинги останутся ссылками и их (пока они не умрут) можно будет посмотреть из просмотрщика.
      3) Если вы хотите сохранять все скриншоты с внешних сервисов, вам понадобится уметь парсить еще и их.


      1. forgotten
        26.01.2016 13:50
        +1

        Просто видеть html страницы as is было бы достаточно ;)


        1. strayge
          26.01.2016 20:17

          В общем я посмотрел, спарсить порнолаб можно, нужна минимальная переделка скрипта.
          Основная выявленная проблема: на странице не публикуется хэш раздачи, необходимо качать torrent-файл и вытаскивать из него.
          Для нового пользователя ограничение — 5 торрентов в сутки. А без хэшей база и не особо нужна.


          1. forgotten
            26.01.2016 21:12

            Положим, пользователь не новый )


            1. strayge
              26.01.2016 21:30

              Максимум 100 торрентов в день: pornolab.net/forum/viewtopic.php?t=980552#4
              Даже с такой скоростью всю базу выкачивать сильно затратно по времени.
              Можно выкачивать только определенные разделы, или только наиболее популярные раздачи.
              Например, сейчас только 400 раздач имеют > 200 сидов.


      1. dmitry_dvm
        27.01.2016 18:42

        Для одного моего знакомого делал функцию для телеграм-бота, чтобы по определенному запросу боту он отвечал случайной ссылкой с порнолаба, но не осилил отделить ссылки именно на раздачи от ссылок на разделы и прочих ссылок. Нет мыслей как там всё это реализовано? В каких диапазонах лежат айди раздач?


        1. strayge
          27.01.2016 18:43

          Идентификатор просто икрементируется, разделения по типам нет. Для такой задачи нужно пройти по всем id и сохранить тип.


          1. dmitry_dvm
            27.01.2016 19:41

            То есть нельзя без предварительного парсинга сделать рабочий алгоритм?


            1. strayge
              27.01.2016 19:53

              Можно случайно перебирать, пока не попадешь на раздачу, для этого даже логиниться не надо.
              А номера, где нет раздач, например, запоминать, чтобы больше их не дергать.


  1. EvilsInterrupt
    26.01.2016 14:10

    >>На момент начала работы над скриптом, rutracker еще не выкладывал свою базу
    А можно др.линк на базу или MD5 от файла?


    1. strayge
      26.01.2016 14:27
      +1

      magnet-hash: 628F28C998A79D780455DC1B60892DD721EE44D1 (от 15.01.2016)


  1. devcor
    28.01.2016 12:09

    Кхм, простите не сведущего в этих делах, но зачем всё-таки это было сделано? Нет, я прочитал секцию «зачем» и всё равно не понял, зачем это делать при работающем сайте.


    1. strayge
      28.01.2016 12:16

      В первую очередь писалось для себя, чтобы поднять свой уровень Python.
      Даже в таком простеньком GUI мне удобнее искать, чем на сайте: для примера попробуйте на сайте найти топ популярных аудиокниг.
      В моей программе достаточно в поле категорий ввести «аудиокниги».