Code Golf Image Downloader

20

ADVERTENCIA: Las respuestas pueden ser útiles para algunos golfistas de código.

En muchos desafíos de , la publicación contiene imágenes, que deben guardarse en un archivo para poder resolver el problema. Esta es una tarea manual especialmente tediosa. Nosotros, los programadores, no deberíamos tener que ser sometidos a tal trabajo pesado. Su tarea es descargar automáticamente todas las imágenes contenidas en una pregunta de Code Golf.SE.

Reglas

  • Su programa puede conectarse a cualquier parte de stackexchange.com, pero no puede conectarse a ningún otro dominio, excepto las ubicaciones de las imágenes (es decir, no se moleste con un acortador de URL).
  • Un entero N se da como entrada, en la línea de comando o stdin.
  • Se garantiza que la URL es un enlace válido a una pregunta de Code Golf.http://codegolf.stackexchange.com/questions/N
  • Cada imagen que se muestra en el cuerpo de la pregunta N debe guardarse en un archivo en la computadora local. Cualquiera de las siguientes ubicaciones es aceptable:
    • El directorio actual
    • Una entrada de directorio por el usuario
  • Su programa no debe guardar archivos que no sean las imágenes en el cuerpo de la pregunta (por ejemplo, avatares de usuario o imágenes contenidas en las respuestas).
  • Las imágenes deben guardarse con la misma extensión de archivo que la original.

Este es un : escriba el programa más corto que pueda.

Criterio de validez para respuestas

Hay varios casos límite posibles con múltiples imágenes del mismo nombre, texto con el mismo nombre que elementos HTML, etc. Una respuesta se invalidará solo si se puede demostrar que falla en alguna revisión de una pregunta publicada antes del 10 de enero de 2015 .

Feersum
fuente
Si los nombres de las imágenes se mantienen iguales o podemos hacer como 0.png, 1.png, etc.
stokastic
@stokastic Puede nombrar la parte antes de la extensión como desee (siempre que no use el mismo nombre dos veces, sobrescribiendo un archivo anterior).
feersum

Respuestas:

10

Mathematica, 211 210 bytes

i=Import;FileNameTake@#~Export~i@#&/@ImportString["body"/.("items"/.i["http://api.stackexchange.com/2.2/questions/"<>InputString[]<>"?site=codegolf&filter=!*Lgp.gEWHA6BNP.l","JSON"])[[1]],{"HTML","ImageLinks"}]

Sin golf:

i = Import;
FileNameTake@#~Export~i@# & /@ 
 ImportString[
  "body" /. (
    "items" /. 
      i["http://api.stackexchange.com/2.2/questions/" <> 
        InputString[] <> "?site=codegolf&filter=!*Lgp.gEWHA6BNP.l", 
       "JSON"]
  )[[1]], 
  {"HTML", "ImageLinks"}
 ]

Es bastante sencillo. He configurado un filtro para la API de StackExchange, que solo devuelve el cuerpo de una pregunta. El código recupera la información de la pregunta con ese filtro y la analiza como JSON. Selecciono el elemento correcto (el cuerpo) y lo uso ImportStringpara analizar el HTML y filtrar todas las URL de las imágenes. FileNameTake@#~Export~Import@#luego descarga cada una de las imágenes y la almacena en el directorio de trabajo actual con el mismo nombre de archivo que el de la URL.

Puede encontrar el directorio de trabajo actual con Directory[].

En principio, hay una versión mucho más corta, porque en ImportStringrealidad puede descargar todos los archivos de inmediato, en lugar de solo darme las URL. Pero luego pierdo información sobre el tipo de archivo original (ya que se convierten en Imageobjetos tras la descarga), por lo que solo puedo guardarlos como el mismo tipo (PNG, por ejemplo).

Martin Ender
fuente
8

Javascript - 149 161 bytes

$.get("http://codegolf.stackexchange.com/q/"+prompt(),function(e){$(".post-text:first img",e).each(function(e,t){$('<a href="'+t.src+'"download>')[0].click()})})

con espacios en blanco

$.get('http://codegolf.stackexchange.com/q/' + prompt(), function(d) {
  $('.post-text:first img',d).each(function(i,e){
   $('<a href="' + e.src + '"download>')[0].click();
  })
})

el script debe ejecutarse desde el sitio stackexchange para funcionar. Se establecerá de forma predeterminada en la página actual si no se especifica ningún número de pregunta en la solicitud

Profesor Allman
fuente
1
Como @doorknob mencionó anteriormente, puede ahorrar un poco cambiando q por pregunta. Y si no te importa obtener todas las imágenes en las publicaciones de la página, puedes hacerlo $('[src*="imgur"]',d), creo. Me gusta que esto se pueda ejecutar en la consola: gratificación instantánea.
Josiah
1
questionspuede acortarse q, pero debe incluir la codegolf.stackexchange.comparte en lugar de depender de estar en esa página. @Josiah es posible incluir imágenes de otros dominios en las publicaciones.
fiesta del
1
El selector #question .post-text imgse puede acortar a .post-text:first imgo .post-text:eq(0) img.
cPu1
5

Python 2 - 241 bytes

Bastante sencillo, probablemente se pueda jugar más al golf. Busco en el sitio todas las ocurrencias img src=entre la primera aparición post-texty la /divinmediatamente posterior. Cada url de imagen se lee y se guarda en el directorio de trabajo.

import string,sys,urllib,re;o=string.find;u=urllib.urlopen
r=u("http://codegolf.stackexchange.com/q/"+sys.argv[1]).read()
i=o(r,"post-text")
for p in re.findall(r'img src="([^"]*)',r[i:o(r,"/div",i)]):f=open(p[-9:],"wb");f.write(u(p).read())
estocástico
fuente
Los nombres de los archivos se conservan tal como están: el nombre se toma como los últimos 9 bytes ( [-9:]) de la url de la imagen, que debe mantener su nombre de 5 caracteres y .pngao .jpgetc. Cortará los bytes del nombre de archivo si la extensión tiene más de 3 caracteres .
stokastic
¿Qué pasa si el nombre del archivo es más corto que 9 bytes? ¿No incluiría eso una barra en el nombre del archivo?
Martin Ender
puede guardar 2 bytes haciendo que el forbucle sea una línea. for p re.findall(...):f=open(...);f.write(...)
undergroundmonorail
@mar No creo que el nombre del archivo pueda tener menos de 9 bytes, pero podría estar equivocado
undergroundmonorail
@ MartinBüttner Creo que 9 bytes es una suposición razonable, pero puedo cambiarlo si crees que debería hacerlo. Para lo que vale, usar solo 6 o 7 bytes es probablemente suficiente y aún garantizará nombres de archivo distintos.
estocástico
2

Mathematica, 195

x=XMLElement;c=Cases;i=Import;l=Infinity;FileNameTake@#~Export~i@#&/@(((c[#,x["img",{"src"->e_,_},___]:>e,l]&)@*(c[#,x[_,{__,"id"->"question",__},e_]:>e,l]&)@*(i[#,"XMLObject"] &))@InputString[])

Esto exporta imágenes de la misma manera que Martin hizo en su solución de Mathematica, lea su respuesta para obtener más información al respecto. Este enfoque es muy diferente al suyo, en lugar de analizar el resultado de la API, analizo la página HTML directamente. O, mejor dicho, analizo el XML simbólico que Mathematica puede generar a partir de HTML.


fuente
1

Python 2 - 398 342 334 bytes

El programa descarga la página SE, extrae la parte de publicación (el elemento div post-texto), encuentra las URL que terminan en una extensión de imagen y las descarga. Las imágenes se guardan como img<n>.<ext>en el directorio actual.

import urllib2 as u,re,sys
z=u.urlopen;i=1
p=z('http://codegolf.stackexchange.com/q/'+sys.argv[1]).read()
s=re.search(r'ss="po(.+?)/di',p,16).group(1)
for L in re.findall('"(h.+?://.*?)"',s):
 b=L.rsplit('.',1)
 if len(b)==2 and b[1].lower() in 'jpg jpeg png gif bmp'.split():
  open('img%u.%s'%(i,b[1]),'wb').write(z(L).read());i+=1

Este programa también descargará imágenes que se proporcionan como un enlace, no solo imágenes incrustadas. Al dar a cada imagen un nombre de archivo único, también se evitan los conflictos de nombres.

Caballero Lógico
fuente
2
Puede guardar 8 caracteres reemplazándolos questionscon q(en la URL).
Pomo de la puerta
En la pregunta 43274, solo veo 11 imágenes, pero 21 se descargan.
feersum
Mi programa descarga las 10 imágenes de alta resolución, así como las 10 miniaturas. No estoy seguro de que las otras entradas obtengan las versiones de alta resolución.
Caballero Lógico
@Doorknob: gracias. Me lo perdí. Aunque necesitaré mucho más para atrapar a los otros chicos.
Logic Knight
1
@CarpetPython, aunque podría decirse que es más útil ... la intención de la especificación era descargar solo las imágenes que son visibles.
feersum
1

Bash - 86 bytes

wget -r -l1 -np -Ajpg,jpeg,png,bmp,gif http://codegolf.stackexchange.com/questions/$1

Nada wget no solucionará. -npevita que wget ingrese directorios superiores (Imgs de usuario) -Asolo toma archivos con la extensión que coincide con la lista presentada. -res una descarga recursiva -levita que wget vaya demasiado profundo. $1es la pregunta para agarrar.

HSchmale
fuente
1
¿Hay algo específico que deba hacer para que esto funcione? Lo intenté en un par de preguntas, pero no fue bueno. Salida aquí .
Geobits
1
Creo que puede guardar 8 caracteres reemplazando questionscon qen la URL.
Timtech
1

Nodo.js, 251 247 bytes

r=require,g=r('request'),g('http://codegolf.stackexchange.com/q/'+process.argv[2],function(_,_,b){r('cheerio').load(b)('#question .post-text img').each(function(i,a){s=a.attribs.src,g(s).pipe(r('fs').createWriteStream(i+r('path').basename(s)))})})

Se utiliza requestpara hacer HTTP GETsy cheeriopara analizar el HTML. Las colisiones de nombres se resuelven anteponiendo el índice de la imagen actual al nombre base de la URL del archivo. Las imágenes se guardan en el mismo directorio que el archivo actual.

cPu1
fuente
1

Lua, 200 bytes

r=require'socket.http'.request r('http://codegolf.stackexchange.com/questions/'.. ...):gsub('post.text(.-)div',function(p)p:gsub('src="(.-)"',function(i)io.open(i:sub(-9),'wb'):write((r(i)))end)end)

Acepta el número como argumento de línea de comando.

Asume que cualquier src=atributo será para una imgetiqueta ya que estas son las únicas etiquetas con srcatributos que permite el intercambio de pila (¿verdad?).

También tenga en cuenta el .. .... Estoy particularmente orgulloso de eso.

thenumbernine
fuente