Code Golf Image Downloader

20

AVISO: As respostas podem ser úteis para alguns jogadores de código.

Em muitos desafios de , a postagem contém imagens, que devem ser salvas em um arquivo para poder solucionar o problema. Esta é uma tarefa manual especialmente tediosa. Nós, programadores, não devemos ter que ser submetidos a essa labuta. Sua tarefa é baixar automaticamente todas as imagens contidas em uma pergunta do Code Golf.SE.

Regras

  • Seu programa pode se conectar a qualquer parte stackexchange.com, mas não a outros domínios, exceto os locais das imagens (ou seja, não se preocupe com um encurtador de URL).
  • Um número inteiro N é dado como entrada, na linha de comando ou stdin.
  • O URL é garantidamente um link válido para uma pergunta do Code Golf.http://codegolf.stackexchange.com/questions/N
  • Cada imagem exibida no corpo da pergunta N deve ser salva em um arquivo no computador local. Qualquer um dos seguintes locais é aceitável:
    • O diretório atual
    • Uma entrada de diretório pelo usuário
  • Seu programa não deve salvar outros arquivos além das imagens no corpo da pergunta (por exemplo, avatares de usuários ou imagens contidas nas respostas).
  • As imagens devem ser salvas com a mesma extensão de arquivo que o original.

Este é um - escreva o programa mais curto possível.

Critério de validade para respostas

Existem vários casos possíveis de borda com várias imagens com o mesmo nome, texto com o mesmo nome que os elementos HTML etc. Uma resposta será invalidada apenas se for demonstrado que falha em alguma revisão de uma pergunta postada antes de 10 de janeiro de 2015 .

feersum
fonte
Caso os nomes de imagem ser mantido o mesmo ou podemos fazer como 0.png, 1.png etc
stokastic
@stokastic Você pode nomear a parte anterior à extensão para o que quiser (desde que não use o mesmo nome duas vezes, substituindo um arquivo anterior).
feersum

Respostas:

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"}]

Ungolfed:

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"}
 ]

É bem direto. Eu configurei um filtro para a API StackExchange, que retorna apenas o corpo de uma pergunta. O código recupera as informações da pergunta com esse filtro e as analisa como JSON. Seleciono o elemento correto (o corpo) e uso ImportStringpara analisar o HTML e filtrar todos os URLs da imagem. FileNameTake@#~Export~Import@#em seguida, baixa cada uma das imagens e as armazena no diretório de trabalho atual com o mesmo nome de arquivo que o URL.

Você pode descobrir o diretório de trabalho atual com Directory[].

Em princípio, há uma versão muito mais curta, porque ImportStringpode realmente baixar todos os arquivos imediatamente, em vez de apenas me fornecer os URLs. Mas, então, perco informações sobre o tipo de arquivo original (uma vez que elas são convertidas em Imageobjetos no download), para que eu possa salvá-las todas apenas do mesmo tipo (por exemplo, PNG).

Martin Ender
fonte
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()})})

com espaço em branco

$.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();
  })
})

O script deve ser executado no site stackexchange para funcionar. O padrão será a página atual se nenhum número de pergunta for especificado no prompt

Professor Allman
fonte
1
Como o @doorknob mencionado acima, você pode economizar um pouco trocando q pela pergunta. E se você não se importa de obter todas as imagens nas postagens da página, $('[src*="imgur"]',d)acredito que sim . Eu gosto que isso possa ser executado no console - gratificação instantânea.
Josias
1
questionspode ser reduzido para q, mas deve incluir a codegolf.stackexchange.comparte em vez de depender de estar nessa página. @ Josiah, é possível incluir imagens de outros domínios nas postagens.
precisa saber é
1
O seletor #question .post-text imgpode ser reduzido para .post-text:first imgou .post-text:eq(0) img.
CPU1
5

Python 2 - 241 bytes

Bem simples, provavelmente pode ser ainda mais jogado. Pesquisei no site todas as ocorrências img src=entre a primeira ocorrência post-texte a /divseguinte imediatamente. Cada URL da imagem é então lido e salvo no diretório de trabalho.

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())
stokastic
fonte
Os nomes de arquivos são mantidos como estão - o nome é usado como os últimos 9 bytes ( [-9:]) do URL da imagem, que deve manter o nome de 5 caracteres e um .pngou .jpgetc. Ele cortará os bytes do nome do arquivo se a extensão tiver mais de 3 caracteres .
stokastic
E se o nome do arquivo for menor que 9 bytes? Isso não incluiria uma barra no nome do arquivo?
Martin Ender
você pode economizar 2 bytes criando o forloop em uma linha. for p re.findall(...):f=open(...);f.write(...)
Undergroundmonorail
@mar Eu não acho que o nome do arquivo pode ser inferior a 9 bytes, mas eu poderia estar enganado
undergroundmonorail
@ MartinBüttner Acho que 9 bytes é uma suposição razoável, mas posso alterá-la se achar que devo. Pelo que vale a pena - usar apenas 6 ou 7 bytes é provavelmente suficiente e ainda garantirá nomes de arquivos distintos.
stokastic
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[])

Isso exporta imagens da mesma maneira que Martin em sua solução Mathematica, leia sua resposta para obter mais informações sobre isso. Essa abordagem é muito diferente da dele, em vez de analisar o resultado da API, analiso a página HTML diretamente. Ou melhor, analiso o XML simbólico que o Mathematica pode gerar a partir do HTML.


fonte
1

Python 2 - 398 342 334 bytes

O programa baixa a página SE, extrai a parte da postagem (o elemento div pós-texto), localiza URLs que terminam em uma extensão de imagem e os baixa. As imagens são salvas como img<n>.<ext>no diretório atual.

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 também fará o download de imagens fornecidas como um link, não apenas imagens incorporadas. Ao atribuir a cada imagem um nome de arquivo exclusivo, conflitos de nome também são evitados.

Cavaleiro Lógico
fonte
2
Você pode salvar 8 caracteres substituindo questionspor q(na URL).
Maçaneta
Na pergunta 43274, vejo apenas 11 imagens, mas 21 são baixadas.
precisa saber é
Meu programa baixa as 10 imagens de alta resolução e as 10 miniaturas. Não tenho certeza de que as outras entradas busquem as versões de alta resolução.
Logic Knight
@ Doorknob - obrigado. Eu senti falta disso. Vou precisar de muito mais para pegar os outros caras.
Logic Knight
1
@CarpetPython, embora isso seja indiscutivelmente mais útil ... a intenção da especificação era baixar apenas imagens visíveis.
precisa saber é
1

Bash - 86 bytes

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

Nada será resolvido. -npimpede que o wget entre nos diretórios superiores (User Imgs) -Aapenas captura arquivos com a extensão correspondente à lista apresentada. -ré um download recursivo. -limpede que o wget seja profundo demais. $1é a pergunta a agarrar.

HSchmale
fonte
1
Preciso fazer algo específico para que isso funcione? Eu tentei em algumas perguntas, mas não é bom. Saída aqui .
Geobits
1
Eu acho que você pode salvar 8 caracteres substituindo questionspor qno URL.
Timtech 14/01
1

Node.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)))})})

Usa requestpara criar HTTP GETe cheerioanalisar o HTML. As colisões de nomes são resolvidas adicionando o índice da imagem atual ao nome da base do URL do arquivo. As imagens são salvas no mesmo diretório que o arquivo atual.

cPu1
fonte
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)

Aceita o número como um argumento de linha de comando.

Supõe que qualquer src=atributo será para uma imgtag, pois essas são as únicas tags com srcatributos permitidos pela troca de pilhas (certo?).

Observe também o .. .... Estou particularmente orgulhoso disso.

thenumbernine
fonte