Detectar preguntas duplicadas

20

Detectar preguntas duplicadas

Érase una vez, había un sitio de golf. Tenía un problema: la gente publicaba preguntas similares o idénticas una y otra vez. Usted ha sidoelegido seleccionado forzado reclutado chantajeado solicitó automatizar el proceso de decidir si una pregunta es un duplicado de una existente, por cualquier medio necesario (ver Reglas).

Entrada

Su programa debe aceptar una sola URL como entrada. Se puede suponer que esto lleva a una pregunta en codegolf.stackexchange.com .

Salida

Busque en el sitio preguntas similares. Si cree que la pregunta de entrada es un duplicado de una pregunta existente (o viceversa), envíe la URL de la otra pregunta. Puede generar varias URL, separadas por nuevas líneas. Al final de su salida, salida end(en una línea separada).

Puntuación

  • Si una pregunta que emitió se marcó como un duplicado de la pregunta de entrada (o viceversa), obtendrá 4 puntos. Esta es una "suposición correcta".
  • Por cada falso positivo (también conocido como "conjetura incorrecta"), pierde 2 puntos.
  • Por cada pregunta que en realidad era un duplicado pero que no aparece en su salida (también conocida como "conjetura faltante"), pierda 1 punto.

El puntaje más alto después de manejar 32 preguntas de entrada gana. Estas 32 preguntas son una "ronda". Al comienzo de cada ronda, los puntajes se restablecerán a 0. Se ejecutará una ronda cada pocos días y la tabla de clasificación se actualizará después de cada ronda.

Reglas

  • Si las preguntas A y C están cerradas como duplicados de B, A contará como un duplicado de C y viceversa.
  • Al comienzo de cada ronda, es posible que su programa no posea ningún dato sobre ninguna pregunta (es decir, sin codificación fija ), excepto sobre cómo analizar el sitio web.
  • Sin embargo, puede mantener datos en archivos externos durante una ronda.
  • No se pueden guardar datos entre rondas.
  • Su salida debe tener una nueva línea final.
  • No puede utilizar ningún dato del sitio web, excepto los resultados de búsqueda y la URL, el título, las etiquetas y el texto de una pregunta , con o sin formato. Por ejemplo, no puede usar el texto "marcado como duplicado por foo, bar ..." que aparece en las preguntas duplicadas.
  • Puede recuperar estos datos directamente desde el sitio, a través de data.SE o a través de la API.
  • Cada envío debe tener un nombre.
  • Cada envío debe tener una numeración clara de la versión.
  • Si un envío no produce resultados después de un límite de tiempo (por decidir; indique cuánto tiempo tarda su envío), se eliminará y perderá 8 puntos.

fuente
2
¿No es subjetivo 1 minuto? Las conexiones de red y el rastreo conducirán a una gran cantidad de solicitudes web. Fácilmente puede tomar más de 1 minuto para todos :)
Optimizer
44
Creo que no podemos llegar directamente a ese número, puede que tenga que escribir un programa de ejemplo usted mismo (o usar la primera respuesta) para determinar el tiempo umbral correcto.
Optimizador
77
En lugar de raspar el sitio, debe pasar por la API y especificar qué campos se pueden usar.
Gilles 'SO- deja de ser malvado'
55
Sería muy divertido si esta pregunta fuera un duplicado ... oh, la ironía xD
Teun Pronk
3
@professorfish Realmente podrías usar algunos casos de prueba, aquí tienes. Todos estos datos provienen de Data.SE, por lo que deberían ser confiables. Siéntete libre de hacerme parecer tonto y demostrarme que estoy equivocado. Esta pregunta tiene codegolf.stackexchange.com/q/37737 no tiene duplicados. Esta pregunta codegolf.stackexchange.com/q/12348 tiene este codegolf.stackexchange.com/q/10465 Esta pregunta codegolf.stackexchange.com/q/12498 tiene estos codegolf.stackexchange.com/q/20006 codegolf.stackexchange.com/ q / 242
PenutReaper

Respuestas:

3

Python 3

Le estoy dando a esta entrada el nombre The Differ.

Código:

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")

El filtro "!-*f(6rc.cI8O"incluía el totalparámetro en el objeto contenedor global y el bodyparámetro en las preguntas.

Esta entrada realiza dos solicitudes de API más una por etiqueta en la pregunta más una por cien preguntas en su etiqueta menos utilizada. Si golpea un acelerador API (que no comprueba), elevará unurllib.error.HTTPError: HTTP Error 400: Bad Request

pppery
fuente