Участник:BsivkoBot/НЕССЫЛ

Описание

Мотивация

Согласно действующим правилам существует ряд случаев, когда простановка викиссылок не нужна и наносит вред проекту. Излишняя викификция делает интерфейс менее дружественным (текст менее читаемым и т.п.), и не приносит ничего полезного, например по тривиальным ссылкам читатели не переходят (на один и тот же год например или на всем известное понятие). Подобные явления и что делать с ними частично описаны в ВП:НЕССЫЛ. Соответственно, полезным делом является избавление текста статей от подобных явлений.

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

Реализация

В статьях о компьютерных играх в карточке возможно указание множества дат выпуска, анонса, выхода версий и др. Лишние ссылки на месяцы, дни года, года и т.д. избыточны. Кроме того, практика показывает, что ссылаться лучше на годы в компьютерных играх (2000) но не на год как таковой (2000). Также, исходя из практики, значимым является первый год выпуска (возможно выхода в ранний доступ, если игра ещё не вышла в полноценной версии). Таким образом, отсюда формализуется следующая задача: во всех карточках компьютерных игр убрать ссылки на месяца, дни года, ссылки на года перенаправить на года в компьютерных играх, и из последних оставить только первую в поле «дата выпуска/даты выпуска».

Для обработки взяты года с 1950 по 2040. Пока что вне их компьютьерных игр почти нет.

Удаляются ссылки на месяца (январь, февраль, ..), сам год, на дни года (1 января, 31 октября, ..). Года (2000) преобразуются в ссылки на года КИ (2000 год в компьютерных играх).

Добавлено преобразование шаблона {{vgy}} в ссылки на года. Т.е. {{vgy|2000}} заменяется на [[2000 год в компьютерных играх|2000]].

Исходный код

import mwparserfromhell

from wiki_requests.redirects import get_redirects_to_page

TASK_DESCRIPTION_DATE_UNLINK = u"ВП:НЕССЫЛ (даты)"

YEAR_FROM = 1950
YEAR_TO = 2040


def gen_dates():
    dates = []
    for i in range(1, 32):
        dates.append(str(i) + " января")
        if i < 30:
            dates.append(str(i) + " февраля")
        dates.append(str(i) + " марта")
        if i < 31:
            dates.append(str(i) + " апреля")
        dates.append(str(i) + " мая")
        if i < 31:
            dates.append(str(i) + " июня")
        dates.append(str(i) + " июля")
        dates.append(str(i) + " августа")
        if i < 31:
            dates.append(str(i) + " сентября")
        dates.append(str(i) + " октября")
        if i < 31:
            dates.append(str(i) + " ноября")
        dates.append(str(i) + " декабря")

    return dates


def gen_years():
    years = []
    for i in range(YEAR_FROM, YEAR_TO):
        years.append(str(i) + " год")
        years.append(str(i))
        years.append(str(i) + " год в играх")
        years.append(str(i) + " год в компьютерных играх")

    return years


def gen_years_cg_mapping():
    years = {}
    for i in range(YEAR_FROM, YEAR_TO):
        years[str(i) + " год"] = str(i) + " год в компьютерных играх"
        years[str(i)] = str(i) + " год в компьютерных играх"

    return years


def substr_years_vgy_template(text):
    for i in range(YEAR_FROM, YEAR_TO):
        text = text.replace("{{vgy|" + str(i) + "}}", "[[" + str(i) + " год в компьютерных играх|" + str(i) + "]]")
        text = text.replace("{{Vgy|" + str(i) + "}}", "[[" + str(i) + " год в компьютерных играх|" + str(i) + "]]")

    return text


def remove_constants(text):
    months = ["январь", "февраль", "март", "апрель", "май", "июнь", "июль",
              "август", "сентябрь", "октябрь", "ноябрь", "декабрь"]

    dates = gen_dates()

    to_remove = []

    to_remove.extend(get_redirects_to_page("год"))

    for i in months:
        to_remove.extend(get_redirects_to_page(i))

    for i in dates:
        to_remove.append(i)
        # to_remove.extend(get_redirects_to_page(i))

    parsed = mwparserfromhell.parse(text)

    for wikilink in parsed.filter_wikilinks():
        if str(wikilink.title).lower() in to_remove:
            to_replace = str(wikilink.title)
            if wikilink.text is not None:
                to_replace = str(wikilink.text)
            parsed.replace(wikilink, mwparserfromhell.nodes.text.Text(to_replace))

    output = str(parsed)

    return output


def remove_all_years(text):
    to_remove = []

    for i in gen_years():
        to_remove.append(i)

    parsed = mwparserfromhell.parse(text)

    for wikilink in parsed.filter_wikilinks():
        text = str(wikilink.title).lower().replace("\xa0", " ")
        if text in to_remove:
            to_replace = str(wikilink.title)
            if wikilink.text is not None:
                to_replace = str(wikilink.text)
            parsed.replace(wikilink, mwparserfromhell.nodes.text.Text(to_replace))

    output = str(parsed)

    return output


def remove_all_years_except_first(text):
    to_remove = []

    for i in gen_years():
        to_remove.append(i)

    parsed = mwparserfromhell.parse(text)

    first = True

    for wikilink in parsed.filter_wikilinks():
        text = str(wikilink.title).lower().replace("\xa0", " ")
        if text in to_remove:
            if first:
                first = False
                continue
            to_replace = str(wikilink.title)
            if wikilink.text is not None:
                to_replace = str(wikilink.text)
            parsed.replace(wikilink, mwparserfromhell.nodes.text.Text(to_replace))

    output = str(parsed)

    return output


def convert_years_wikilinks_to_cg(text):
    mapping = gen_years_cg_mapping()

    parsed = mwparserfromhell.parse(text)

    for wikilink in parsed.filter_wikilinks():
        key = str(wikilink.title).lower()
        if key in mapping.keys():
            if wikilink.text is not None:
                to_replace = str("[[" + mapping[key] + "|" + str(wikilink.text) + "]]")
            else:
                to_replace = str("[[" + mapping[key] + "|" + key + "]]")
            parsed.replace(wikilink, mwparserfromhell.nodes.text.Text(to_replace))

    output = str(parsed)

    return output


def except_first(template, params):
    for i in params:
        if template.has(i):
            value = str(template.get(i).value).replace("\xa0", " ")
            value = remove_constants(value)
            value = substr_years_vgy_template(value)
            value = remove_all_years_except_first(value)
            value = convert_years_wikilinks_to_cg(value)
            template.get(i).value = value

    pass


def remove_all(template, params):
    for i in params:
        if template.has(i):
            value = str(template.get(i).value).replace("\xa0", " ")
            value = remove_constants(value)
            value = substr_years_vgy_template(value)
            value = remove_all_years(value)
            value = convert_years_wikilinks_to_cg(value)
            template.get(i).value = value

    pass


def unlink_for_article(text, names, title="unknown"):
    for index, item in enumerate(names):
        if names[index][:7] == "Шаблон:": names[index] = names[index][7:]

    parsed = mwparserfromhell.parse(text)

    for template in parsed.ifilter_templates():

        matches = False
        for name in names:
            if template.name.matches(name):
                matches = True
                break

        if not matches:
            continue

        except_first(template, ['даты выпуска', 'дата выпуска'])
        remove_all(template, [
            'дата анонса', 'разработчик', 'разработчики', 'локализатор', 'локализаторы', 'издатель', 'издатели',
            'язык интерфейса', 'языки интерфейса', 'серия', 'платформа', 'платформы', 'движок', 'движки',
            'лицензия', 'бюджет', 'версия', 'жанр', 'жанры', 'режим', 'режимы', 'рейтинг', 'рейтинги',
            'носитель', 'носители', 'системные требования', 'сайт', 'управление', 'подпись', 'дата последней версии'
        ])

    output = str(parsed)

    return output

Тестирование

from dates.format import date_to_ggggmmdd_format, check_regular_wiki_date_formats
from dates.unlink import remove_constants, remove_all_years, remove_all_years_except_first, \
    convert_years_wikilinks_to_cg, substr_years_vgy_template
from wiki_requests.redirects import get_redirects_to_template


def test_remove_constants():
    assert remove_constants('{cite}') == '{cite}'
    assert remove_constants('{cite}\n') == '{cite}\n'
    assert remove_constants('2000-10-10') == '2000-10-10'
    assert remove_constants("[[январь|10 января]] 2000") == "10 января 2000"
    assert remove_constants("[[Январь|10 января]] 2000") == "10 января 2000"
    assert remove_constants("[[июль]] 2001") == "июль 2001"
    assert remove_constants("[[Июль]] 2001") == "Июль 2001"
    assert remove_constants("[[10 января]] 2000") == "10 января 2000"
    assert remove_constants("[[10 января|10 января]] 2000") == "10 января 2000"
    assert remove_constants("[[10 Января|10 января]] 2000") == "10 января 2000"
    assert remove_constants("[[31 октября]] 2000") == "31 октября 2000"


def test_remove_all_years():
    assert remove_all_years('{cite}') == '{cite}'
    assert remove_all_years('{cite}\n') == '{cite}\n'
    assert remove_all_years('2000-10-10') == '2000-10-10'
    assert remove_all_years("[[июль]] [[2001 год]]") == "[[июль]] 2001 год"
    assert remove_all_years("[[июль]] [[2001]]") == "[[июль]] 2001"
    assert remove_all_years("[[июль]] [[2001 год]]а") == "[[июль]] 2001 года"


def test_remove_all_years_except_first():
    assert remove_all_years_except_first('{cite}') == '{cite}'
    assert remove_all_years_except_first('{cite}\n') == '{cite}\n'
    assert remove_all_years_except_first('2000-10-10') == '2000-10-10'
    assert remove_all_years_except_first("[[июль]] [[2001 год]]") == "[[июль]] [[2001 год]]"
    assert remove_all_years_except_first("[[июль]] [[2001]]") == "[[июль]] [[2001]]"
    assert remove_all_years_except_first("[[2001 год]] [[2000]]") == "[[2001 год]] 2000"
    assert remove_all_years_except_first("[[июль]] [[2001]] [[2011 год|2010]]") == "[[июль]] [[2001]] 2010"
    assert remove_all_years_except_first("[[июль]] [[2001]] [[2011 год|2010]] [[1950]]") == "[[июль]] [[2001]] 2010 1950"
    assert remove_all_years_except_first("[[июль]] [[2001]] [[2011 год|2010]] [[1850]]") == "[[июль]] [[2001]] 2010 [[1850]]"
    assert remove_all_years_except_first("[[июль]] [[2001 год]]а") == "[[июль]] [[2001 год]]а"
    assert remove_all_years_except_first("{{flagicon|Russia}} сентябрь [[2003 год]]а <br />ноябрь [[2003 год]]а") == "{{flagicon|Russia}} сентябрь [[2003 год]]а <br />ноябрь 2003 года"


def test_convert_years_wikilinks_to_cg():
    assert convert_years_wikilinks_to_cg('{cite}') == '{cite}'
    assert convert_years_wikilinks_to_cg('{cite}\n') == '{cite}\n'
    assert convert_years_wikilinks_to_cg('2000-10-10') == '2000-10-10'
    assert convert_years_wikilinks_to_cg("[[июль]] [[2001 год]]") == "[[июль]] [[2001 год в компьютерных играх|2001 год]]"
    assert convert_years_wikilinks_to_cg("[[июль]] [[2001]]") == "[[июль]] [[2001 год в компьютерных играх|2001]]"
    assert convert_years_wikilinks_to_cg("[[2001 год]] [[2000]]") == "[[2001 год в компьютерных играх|2001 год]] [[2000 год в компьютерных играх|2000]]"
    assert convert_years_wikilinks_to_cg("[[июль]] [[2001]] [[2011 год|2010]]") == "[[июль]] [[2001 год в компьютерных играх|2001]] [[2011 год в компьютерных играх|2010]]"
    assert convert_years_wikilinks_to_cg("[[июль]] [[2001]] [[2011 год|2010]] [[1850]]") == "[[июль]] [[2001 год в компьютерных играх|2001]] [[2011 год в компьютерных играх|2010]] [[1850]]"


def test_substr_years_vgy_template():
    assert substr_years_vgy_template('{cite}') == '{cite}'
    assert substr_years_vgy_template('{cite}\n') == '{cite}\n'
    assert substr_years_vgy_template('2000-10-10') == '2000-10-10'
    assert substr_years_vgy_template("{{vgy|2001}}") == "[[2001 год в компьютерных играх|2001]]"
    assert substr_years_vgy_template("{{Vgy|2001}}") == "[[2001 год в компьютерных играх|2001]]"

Состояние и развитие

  • Первые запуски. См. например Duck Hunt. Найдено и исправлено пару ошибок (уточнение диапазона дней года, более полный набор полей). Bsivko (обс.) 18:08, 22 мая 2019 (UTC)
  • Добавлено преобразование non-breakable-space в пробел. Bsivko (обс.) 21:38, 22 мая 2019 (UTC)

Обсуждение