Mostrar un xkcd

36

xkcd es el webcomic favorito de todos, y estarás escribiendo un programa que nos traerá un poco más de humor a todos.
Su objetivo en este desafío es escribir un programa que tomará un número como entrada y mostrará ese xkcd y su texto de título (texto de mousover).

Entrada

Su programa tomará un entero positivo como entrada (no necesariamente uno para el que exista un cómic válido) y mostrará ese xkcd: por ejemplo, una entrada de 1500 debería mostrar el cómic "Mapa invertido" en xkcd.com/1500, y luego imprima el texto del título en la consola o muéstrelo con la imagen.

Debido a su proximidad a través del canal, ha habido una tensión entre Corea del Norte y el Reino Unido de Gran Bretaña e Irlanda del Sur. Due to their proximity across the channel, there's long been tension between North Korea and the United Kingdom of Great Britain and Southern Ireland.

Caso de prueba 2, para n = 859:

Dejando el cerebro a un lado, me pregunto cuántos scripts mal escritos de xkcd.com analizarán este título (o ;; "'' {<< ['este texto al pasar el mouse".

Brains aside, I wonder how many poorly-written xkcd.com-parsing scripts will break on this title (or ;;"''{<<[' this mouseover text."

Su programa también debería poder funcionar sin ninguna entrada, y realizar la misma tarea para el xkcd más reciente encontrado en xkcd.com, y siempre debería mostrar el más reciente, incluso cuando uno nuevo sube.

No es necesario que obtenga la imagen directamente de xkcd.com, puede usar otra base de datos siempre que esté actualizada y ya existiera antes de que este desafío surgiera. Los acortadores de URL, es decir, las URL sin otro propósito que el de redireccionar a otro lugar, no están permitidas.

Puede mostrar la imagen de la forma que elija, incluso en un navegador. Sin embargo, no puede mostrar directamente parte de otra página en un iframe o similar. ACLARACIÓN: no puede abrir una página web preexistente, si desea utilizar el navegador debe crear una nueva página . También debe mostrar una imagen, ya que no está permitido generar un archivo de imagen.

Puede manejar el caso de que no hay una imagen para un cómic en particular (por ejemplo, es interactivo o se le pasó al programa un número mayor que la cantidad de cómics que se han lanzado) de la manera razonable que desee, incluso lanzando una excepción o imprimir una cadena de al menos un solo carácter, siempre que de alguna manera signifique para el usuario que no hay una imagen para esa entrada.

Solo puede mostrar una imagen y generar el texto del título, o generar un mensaje de error para un cómic no válido. Otra salida no está permitida.

Este es un desafío de , por lo que gana la menor cantidad de bytes.

Pavel
fuente
1
@LukeFarritor Solo puede mostrar la imagen y generar el texto del título o generar algún tipo de mensaje de error para un cómic no válido.
Pavel
99
Si el tamaño de su muestra es 1, import antigravityen Python;)
Wayne Werner
15
Dato curioso n=404 xkcd.com/404 es una página 404.
Urna de pulpo mágico
11
xkcd is everyone's favorite webcomic [Cita requerida ]
Sanchises
11
Caso de prueba: 859
betseg

Respuestas:

13

Perl + curl + feh, 86 84 75 bytes

`curl xkcd.com/$_/`=~/<img src="(.*)" title="(.*?)"/;$_=$2;`feh "http:$1"`

Requiere el -pinterruptor. He contado esto en el recuento de bytes.

un espagueti
fuente
@ Matt Funcionó en todos los cómics que probé. Solo coincide con imágenes con texto alternativo.
un espagueti
Es posible que no necesite las comillas alrededor del atributo src.
Conor O'Brien
No creo que necesites el ?en el primer grupo de partidos. Puede usar -py en $_=$2lugar de print$2, pero el texto del título se imprime solo después de cerrar feh. No estoy seguro si eso es válido.
m-chrzan
@ m-chrzan Sí, parece que puedo soltar el cuantificador reacio allí, gracias. Pensé en usar, -ppero no estaba seguro de cómo se sentiría el OP al respecto.
un spaghetto
@ ConorO'Brien Desafortunadamente, Randall observa buenas prácticas de codificación HTML ... y capturar las citas no cita los argumentos debido a cómo funcionan los backticks en Perl.
un spaghetto
9

PowerShell v3 + 110 99 107 103 Bytes

iwr($x=((iwr "xkcd.com/$args").images|?{$_.title})).src.Trim("/") -outf x.jpg;if($x){ii x.jpg;$x.title}

Gracias a Timmy por ayudar a guardar algunos bytes mediante el uso de asignaciones en línea.

Si no se pasan argumentos, entonces $argses nulo y solo obtendrá el cómic actual. Descargue la imagen, haciendo coincidir la que está con el texto alternativo, en un archivo en el directorio actual del script. Luego muéstrelo con el visor predeterminado de jpg's. El texto alternativo se muestra en la consola. iwres un alias paraInvoke-WebRequest

Si el número pasado (o cualquier entrada no válida para ese asunto) no coincide, el proceso falla con al menos un error 404.

iwr(                                  # Request the comic image from XKCD
  $x=((iwr "xkcd.com/$args").images|  # Primary search to locate either the current image
                                      # or one matching an argument passed
     ?{$_.title}))                    # Find the image with alt text
        .src.Trim("/")                # Using the images associated link and strip the leading slashes
  -outf x.jpg                         # Output the image to the directory local to where the script was run
if($x){                               # Test if the image acquisition was successful
    ii x.jpg                          # Open the picture in with the default jpg viewer
    $x.title                          # Display alt text to console
}                                     # I'm a closing bracket.
Mate
fuente
Acabo de recibir mi privilegio de comentario en este sub ahora,
mira
@ConnorLSW Buen enfoque en su respuesta. Cosas para pensar para la próxima vez.
Matt
8

AutoIt , 440 bytes

Sí, es largo, pero es estable.

#include<IE.au3>
#include<GDIPlus.au3>
Func _($0='')
_GDIPlus_Startup()
$1=_IECreate('xkcd.com/'&$0)
For $3 In $1.document.images
ExitLoop $3.title<>''
Next
$4=_GDIPlus_BitmapCreateFromMemory(InetRead($3.src),1)
$6=_GDIPlus_ImageGetDimension(_GDIPlus_BitmapCreateFromHBITMAP($4))
GUICreate(ToolTip($3.title),$6[0],$6[1])
GUICtrlSendMsg(GUICtrlCreatePic('',0,0,$6[0],$6[1]),370,0,$4)
_IEQuit($1)
GUISetState()
Do
Until GUIGetMsg()=-3
EndFunc

En primer lugar, esto no usa RegEx para raspar el sitio (porque no tengo tiempo para probar esto en todos los cómics), sino que usa la API de Internet Explorer para recorrer las imgetiquetas del DOM hasta que encuentre uno con un texto de título.

La secuencia binaria se lee desde la URL de la imagen y se procesa en un mapa de bits usando GDIPlus. Esto se muestra en una interfaz gráfica de usuario agradable y de tamaño automático con una información sobre herramientas real para que se comporte casi exactamente como el sitio web.

Aquí hay un caso de prueba ( _(859)):

)

mınxomaτ
fuente
44
Sería mejor si agregaras el soporte nuevamente a la imagen.
Matt
Wow, acabo de descubrir que puedo ejecutar AutoIt en Wine en Ubuntu. Ahora todo lo que necesito hacer es hacer que IE funcione allí.
Pensándolo bien
2
@ElPedro Si tiene una CPU moderna, use qemu KVM y seamlessRDP (básicamente un paralelo de bricolaje para Linux) en lugar de vino. Esto integra las aplicaciones de Windows sin problemas en el escritorio de Linux y tiene un 100% de compatibilidad + transferencia de GPU. Solo un consejo.
mınxomaτ
Gracias @ mınxomaτ. Puedo darle una oportunidad. Trabajo con Windows todo el día, así que prefiero usar Linux (varios tipos) sin trabajo, pero siempre estoy interesado en experimentar :) Consejo recibido con gratitud.
ElPedro
7

Powershell, 93 bytes

Versión de 93 bytes para usar el visor de imágenes local.

$n=(iwr xkcd.com/$args).images|?{$_.title};$n.title;iwr ("http:"+$n.src) -OutF x.jpg;ii x.*

Ahorró 2 bytes eliminando comillas dobles innecesarias, luego otro lote usando ("http:"+$n.src) lugar de "https://"+$n.src.trim("/"), ya que el imgsrc //ya viene con él, y xkcd no requiere https.

$n=(iwr xkcd.com/$args).images|?{$_.title};$n.title;saps ("http:"+$n.src)

$n=(iwr "xkcd.com/$args").images|?{$_.title};$n.title;saps ("https://"+$n.src.trim("/"))

extremadamente similar a la respuesta de Matts powershell, (probablemente debería ser un comentario pero poca reputación)

En cambio, esto abre una nueva pestaña / ventana en el navegador predeterminado y otras cosas, guardando algunos bytes.

iwr es un alias para Invoke-WebRequest

saps es un alias para Start-Process cual se abre 'it' en el contexto predeterminado.

colsw
fuente
Bordeando los bordes de las reglas sobre la apertura de una página web existente, ya que esto es solo iniciar directamente el navegador en el .jpg preexistente (o lo que sea), pero es una buena respuesta.
AdmBorkBork
@TimmyD podría haber entendido mal aquí, entonces - Supuse que puede utilizar la propia página web xkcd - sólo puede cambiar sapsa iwry anexar `x.jpg -OutF;. Ii x *` hasta el final si desea que se abra en el local por defecto Visor de imágenes.
colsw
1
El OP especificó que no se le permite abrir una página web preexistente. Sin embargo, creo que la versión de 93 bytes está bien
un espagueti el
No creo que esto vaya a funcionar siempre igual si le das un número que funciona y luego un número que no funciona. Se abrirá la imagen que existía en la ejecución anterior.
Matt
Acepto la versión de 93 bytes, pero la versión más corta viola las condiciones del rompecabezas.
Pavel
4

R, 358 328 310 298 bytes

f=function(x){H="http:";p=paste0;library(XML);a=xpathSApply(htmlParse(p(H,'//xkcd.com/',x)),'//div/img',xmlAttrs)[[1]];download.file(p(H,a[1]),'a');I=`if`(grepl('png',a[1]),png::readPNG,jpeg::readJPEG)('a');d=dim(I)/100;quartz(,d[2],d[1]);par(mar=rep(0,4));frame();rasterImage(I,0,0,1,1);cat(a[2])}

Con nuevas líneas y comentarios:

f=function(x){
H="http:"
p=paste0
library(XML) #Needed for xpathSApply, htmlParse and xmlAttrs
# The following line find the first img element and extract its attributes
a=xpathSApply(htmlParse(p(H,'//xkcd.com/',x)),'//div/img',xmlAttrs)[[1]]
download.file(p(H,a[1]),'a') #Download to a file called 'a'
I=`if`(grepl('png',a[1]),png::readPNG,jpeg::readJPEG)('a') #Check if png or jpeg and load the file accordingly
d=dim(I)/100 #convert dimension from pixel to inches (100 ppi).
quartz(,d[2],d[1]) #open a window of the correct dimension
par(mar=rep(0,4)) #Get rid of margins
frame() #Create empty plot
rasterImage(I,0,0,1,1) #Add png/jpeg to the plot
cat(a[2]) #Print title text to stdout
}

Capturas de pantalla de casos de prueba:

para x = 1500: para x = 1500 (png)

para x vacío:
para x = ''

caso cuando la imagen es un JPEG:
para x = 10 (jpeg)

x = 859:
x = 859

plannapus
fuente
Me pregunto si es necesario mostrar la imagen en las dimensiones correctas. Cuando estaba jugando con este desafío, simplemente lo hice plot.new();rasterImage(...).
Billywob
@Billywob Bueno, estaría completamente distorsionado ya que el tamaño predeterminado para la trama es de 7x7 pulgadas. Es cierto que el OP no pidió explícitamente que la imagen no se distorsionara, pero lo prefiero de esta manera :) Sin embargo, estoy considerando deshacerme de él xaxsy, yaxscomo resultado, aún sería proporcionado.
plannapus
3

PHP, 95 bytes

<?php echo str_replace("title=\"","/>",file_get_contents("https://xkcd.com/".$_GET["id"])); ?>

Guardar como main.php, ejecutar servidor

php -S localhost:8123

Abra http: // localhost: 8123 / main.php? Id = 1500

Евгений Новиков
fuente
2

Python 2.7, 309 299 295 274 bytes

Programa completo Definitivamente más golfable, pero después de haber leído los cómics de xkcd durante tanto tiempo no pude dejar pasar esto (quién sabe si esto será útil en el futuro para navegar fácilmente por xkcd).

Si no se pasa ninguna entrada, obtiene el cómic actual. Si se pasa un número de cómic válido como entrada, se obtiene ese cómic. Si se pasa una entrada no válida (no un cómic de número en el rango válido), arroja un error.

¡Cualquier sugerencia sobre cómo reducir el conteo de bytes es bienvenida! Volveré a visitar (y agregaré una explicación) cuando tenga más tiempo.

-10 bytes gracias a @Dopapp

-21 bytes gracias a @Shebang

import urllib as u,re
from PIL import Image
h='http://';x='xkcd.com/'
o=u.URLopener()
t=u.urlopen(h+x+raw_input()).read()
c=sum([re.findall(r,t)for r in[h+'imgs.'+x+'c.*s/.*\.\w{1,3}','\.\w{1,3}" t.*e="(.*)" a']],[])
Image.open(o.retrieve(c[0],'1.png')[0]).show();print c[1]
Ioannes
fuente
1
Puede cambiar try:...y except:...para try:n=...y except:n='', ahorrándole un total de 10 bytes
Daniel
1
¿Por qué tienes una trydeclaración? La especificación del programa dice que siempre obtendrá un número entero positivo.
Kade
@Shebang también debería devolver el último cómic cuando no hay entrada. No pude manejar este caso sin cargar la excepción del error de entrada.
Ioannes
1
@Joannes ¿Por qué no usar raw_input()? Por defecto, el usuario puede presionar [Enter]y ncontendrá la cadena vacía de todos modos. Si elimina ese bloque try-except y t=u.urlopen(h+x+n).read() -> t=u.urlopen(h+x+raw_input()).read()lo reduce a 274 bytes.
Kade
Esto ya no funciona porque las URL de imagen xkcd usan https. Sin embargo, sigue siendo válido, porque funcionaba en el momento de la publicación. Para que funcione ahora, cambie la línea 3 para comenzar con h='https://'+1 byte.
Mego
2

PHP, 42 bytes

<?=@file('http://xkcd.com/'.$_GET[i])[59];

Guarde en un archivo y enciéndalo en el servidor web de su elección

Jared Mellentine
fuente
1
Bienvenido a PPCG! No conozco PHP, pero ¿no parece haber una parte de su código que está recuperando el texto del título de la imagen?
Pavel
1

JavaScript + HTML, 124 + 18 = 142 bytes

i=>fetch(`//crossorigin.me/http://xkcd.com/${i||""}/info.0.json`).then(r=>r.json()).then(d=>(A.innerHTML=d.alt,B.src=d.img))
<img id=B><p id=A>

Solución de origen cruzado gracias a la respuesta de Kaiido aquí .

//crossorigin.me/Se pueden guardar 17 bytes ( ) si se puede restar el proxy requerido para conectarse a xkcd.com ( meta publicación sobre esto ).

Fragmento de prueba

f=
i=>fetch(`//crossorigin.me/http://xkcd.com/${i||""}/info.0.json`).then(r=>r.json()).then(d=>(A.innerHTML=d.alt,B.src=d.img))
<style>img{width:50%}</style><input id=I> <button onclick="f(I.value)">Run</button><br>
<img id=B><p id=A>

Justin Mariner
fuente
1

Python 3 + Solicitudes + PIL, 192 186 bytes

from requests import*
import PIL.Image as f
from io import*
r=get("https://xkcd.com/%s/info.0.json"%input()).json()
f.open(BytesIO(get(r["img"],stream=1).content)).show()
print(r["alt"])

Abre un visor de imágenes (lo que sea predeterminado en el sistema en el que se ejecuta) que contiene el cómic y publica el texto del título en la consola.

LyricLy
fuente
1

Wolfram Language 45 bytes (Mathematica)

Import["https://xkcd.com/"<>#,"Images"][[2]]&

Uso con número:

%@"1500"

Uso sin número:

%@""
Vitaliy Kaurov
fuente