Виявити повторювані запитання


20

Виявити повторювані запитання

Колись тут був майданчик для гольфу. У нього виникли проблеми: люди надсилали подібні чи однакові питання знову і знову. Ви буливибрані вибрані примусові призовники на шантажі вимагається автоматизувати процес вирішення питання, чи є питання дублікатом існуючого, будь-якими способами (див. Правила).

Вхідні дані

Ваша програма повинна прийняти одну URL-адресу як вхідну інформацію. Можна припустити, що це призводить до запитання на codegolf.stackexchange.com .

Вихідні дані

Шукайте на сайті подібні запитання. Якщо ви вважаєте, що вхідне запитання є дублікатом існуючого питання (або навпаки), виведіть URL-адресу іншого питання. Ви можете вивести кілька URL-адрес, розділених новими рядками. В кінці вашого результату виведіть end(окремим рядком).

Оцінка балів

  • Якщо питання, яке ви виводили, було позначене як дублікат вхідного питання (або навпаки), ви набираєте 4 бали. Це "правильна здогадка".
  • За кожен хибний позитив (він же "неправильна здогадка") ви втрачаєте 2 бали.
  • За кожне запитання, яке насправді було дублікатом, але не відображається у ваших результатах (він же "відсутній здогад"), втрачайте 1 бал.

Виграє найвищий бал за 32 вхідні запитання. Ці 32 питання - це «раунд». На початку кожного раунду бали будуть скинуті до 0. Один раунд проводитиметься кожні кілька днів, а таблиця лідерів оновлюється після кожного раунду.

Правила

  • Якщо запитання A і C закриті як дублікати B, A вважатиметься дублікатом C і навпаки.
  • На початку кожного раунду ваша програма може не мати жодних даних щодо будь-яких питань (тобто відсутність жорсткого кодування ), за винятком способів розбору веб-сайту.
  • Однак ви можете зберігати дані у зовнішніх файлах під час раунду.
  • Дані не можуть зберігатися між раундами.
  • У вашому виході повинен бути новий новий рядок.
  • Ви не можете використовувати будь-які дані з веб-сайту, окрім результатів пошуку та URL-адреси, заголовка, тегів та тексту питання , із форматуванням або без нього. Наприклад, ви не можете використовувати текст "позначений як дублікат foo, bar ...", який відображається на дублюючих запитаннях.
  • Ви можете отримати ці дані безпосередньо з сайту, через data.SE або через API.
  • Кожне подання повинно мати ім’я.
  • Кожне подання повинно мати чітку нумерацію версій.
  • Якщо подання не дасть результату через обмежений термін (буде прийнято рішення; будь ласка, вкажіть, скільки часу буде подано), воно буде знищене та втратить 8 балів.

2
Хіба 1 хвилина не є суб’єктивною? Підключення до мережі та сканування призведе до величезної кількості веб-запитів. Для кожного це може зайняти більше 1 хвилини :)
Оптимізатор

4
Я думаю, що ми не можемо прийти безпосередньо до цього числа, можливо, вам доведеться самостійно написати приклад програми (або скористатися першою відповіддю), щоб визначити правильний пороговий час.
Оптимізатор

7
Замість того, щоб скребкувати сайт, слід перейти через API та вказати, які поля можна використовувати.
Жил 'ТАК - перестань бути злим'

5
Було б так смішно, якби це питання було дублікатом .. о, іронія xD
Teun Pronk

3
@professorfish Ви справді можете використати деякі тестові випадки. Усі ці дані надходили з Data.SE, тому вони повинні бути надійними. Не соромтеся змусити мене виглядати дурним і доведіть мене неправильно. У цьому питанні codegolf.stackexchange.com/q/37737 не має дублікатів. Це питання codegolf.stackexchange.com/q/12348 має цей codegolf.stackexchange.com/q/10465 У цьому питанні codegolf.stackexchange.com/q/12498 є ці codegolf.stackexchange.com/q/20006 codegolf.stackexchange.com/ q / 242
PenutReaper

Відповіді:


3

Пітон 3

Я даю цьому запису назву The Differ.

Код:

import urllib.request, gzip, re, json, difflib, sys
API_URL = "https://api.stackexchange.com/"
qurl = input()
qid = int(re.search("\d+",qurl).group(0))
def request(url,wrapper=False,**params):
    params.setdefault("filter","withbody")
    params.setdefault("site","codegolf")
    url = API_URL + url + "?"+"&".join([str(k)+"="+str(v) for k,v in params.items()])
    compressed_response = urllib.request.urlopen(url)
    response = gzip.decompress(compressed_response.read()).decode("utf8")
    response_object = json.loads(response)
    if wrapper:
        return response_object
    else:
        return response_object["items"]
question = request("questions/%s"%qurl)[0]
tags = ";".join(question["tags"])
title = question["title"]
escaped = title.replace(" ","%20")
related = request("similar",title=escaped,pagesize=100)
hasmore = False
length = sys.maxsize
for tag in question["tags"]:
    result = request("search",tagged=tag,
                     wrapper=True,
                     filter="!-*f(6rc.cI8O",
                     pagesize=100)
    if result["total"] < length:
        length = result["total"]
        related.extend(result["items"])
        hasmore = result["has_more"]
        besttag = tag
related.extend(best)
if length < 1500:
    for page in itertools.count(2):
        if not hasmore:
            break
        response = request("search",
                           tagged=besttag,
                           page=page,
                           pagesize=100,
                           filter="!-*f(6rc.cI8O",
                           wrapper=True)
        hasmore = response["has_more"]
        related.extend(result["items"])
matcher = difflib.SequenceMatcher(None, question["body"], None)
titlematcher = difflib.SequenceMatcher(None, question["title"], None)
seen = set()
seen.add(question["question_id"])
for possible in related:
    matcher.set_seq2(possible["body"])
    titlematcher.set_seq2(possible["title"])
    score = matcher.ratio()+titlematcher.ratio()
    qid = possible["question_id"]
    if score > .85 and qid not in seen:
        print(qid)
        seen.add(qid)
print("end")

Фільтр "!-*f(6rc.cI8O"включав totalпараметр на об'єкт глобальної обгортки та bodyпараметр на питання.

Цей запис містить два запити API плюс один на тег питання плюс один на сто питань у його найменш використаному тезі. Якщо він потрапить у дросельний затвор (який він не перевіряє), він піднімеurllib.error.HTTPError: HTTP Error 400: Bad Request

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.