Показать xkcd


36

xkcd - это всеми любимый веб-комикс, и вы будете писать программу, которая принесет нам больше юмора.
Ваша задача в этой задаче - написать программу, которая будет принимать число в качестве входных данных и отображать этот xkcd и его текст заголовка (текст mousover).

вход

Ваша программа примет положительное целое число в качестве входных данных (не обязательно того, для которого существует действительный комикс) и отобразит этот xkcd: например, при вводе 1500 должно отображаться комическое «Upside-Down Map» на xkcd.com/1500, а затем либо напечатайте текст заголовка на консоли, либо отобразите его с изображением.

Из-за их близости через канал долгое время существовала напряженность между Северной Кореей и Соединенным Королевством Великобритании и Южной Ирландии. 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.

Контрольный пример 2, для n = 859:

Помимо мозгов, мне интересно, сколько плохо написанных сценариев разбора xkcd.com сломается для этого заголовка (или ;; "'' {<< ['этот текст при наведении курсора".

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

Ваша программа также должна функционировать без какого-либо ввода и выполнять ту же задачу для самого последнего xkcd, найденного на xkcd.com, и она всегда должна отображать самый последний, даже когда новый выходит.

Вам не нужно получать изображение непосредственно с xkcd.com, вы можете использовать другую базу данных, если она актуальна и уже существовала до того, как возникла эта проблема. Укороченные URL-адреса, то есть URL-адреса, не имеющие цели, кроме перенаправления в другое место, не допускаются.

Вы можете отображать изображение любым удобным для вас способом, в том числе в браузере. Однако вы не можете напрямую отображать часть другой страницы в iframe или аналогичном. УТОЧНЕНИЕ: вы не можете открыть ранее существующую веб-страницу, если вы хотите использовать браузер, вам нужно создать новую страницу . Вы также должны фактически отобразить изображение - вывод файла изображения не допускается.

Вы можете обрабатывать случай, когда для определенного комикса нет изображения (например, оно является интерактивным или программе было передано число, превышающее количество выпущенных комиксов) любым разумным способом, в том числе выбрасывающим исключение. или распечатка, по крайней мере, односимвольной строки, если она каким-то образом показывает пользователю, что для этого ввода нет изображения.

Вы можете только отобразить изображение и вывести его текст заголовка или вывести сообщение об ошибке для недопустимого комикса. Другие выходные данные не допускаются.

Это соревнование по , поэтому выигрывает меньшее количество байтов.


1
@LukeFarritor Вы можете только отобразить изображение и вывести текст заголовка или вывести сообщение об ошибке в той или иной форме для недопустимого комикса.
Павел

9
Если ваш размер выборки равен 1, import antigravityв Python;)
Уэйн Вернер,

15
Забавный факт n=404 xkcd.com/404 это страница 404.
Волшебная Урна Осьминога

11
xkcd is everyone's favorite webcomic [
Требуется

11
Тестовый пример: 859
betseg

Ответы:


13

Perl + curl + feh, 86 84 75 байт

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

Требуется -pвыключатель. Я учел это в подсчете байтов.


@ Matt Это сработало на всех комиксах, которые я пробовал. Это сопоставляет только изображения с альт-текстом
спагетто

Возможно, вам не нужны кавычки вокруг атрибута src.
Конор О'Брайен

Я не думаю, что вам нужно ?в первой группе матча. Вы можете использовать -pи $_=$2вместо print$2, но тогда текст заголовка печатается только после закрытия feh. Не уверен, что это верно.
m-chrzan

@ m-chrzan Да, похоже, я могу бросить неохотный квантификатор, спасибо. Я думал об использовании, -pно не был уверен, что OP будет чувствовать по этому поводу.
спагетто

@ ConorO'Brien К сожалению, Рэндалл соблюдает хорошие практики кодирования HTML ... и захват кавычек не приводит в кавычки аргументы из-за того, как в Perl работают обратные ссылки.
спагетто

9

PowerShell v3 + 110 99 107 103 байт

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

Спасибо Тимми за помощь в сохранении некоторых байтов с помощью встроенных назначений.

Если никакие аргументы не переданы, тогда $argsявляется нулем, и это только получит текущий комикс. Загрузите изображение, сопоставив изображение с альтернативным текстом, в файл в текущем рабочем каталоге скрипта. Затем отобразите его с помощью программы просмотра jpg по умолчанию. Затем альтернативный текст отображается на консоли. iwrэто псевдоним дляInvoke-WebRequest

Если переданное число (или любой неверный ввод по этому вопросу) не совпадает, процесс завершается с ошибкой не менее 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.

Только сейчас я получил право комментировать эту
сабвуфер

@ConnorLSW Хороший подход в вашем ответе. О чем подумать в следующий раз.
Мэтт

8

AutoIt , 440 байт

Да, это долго, но это стабильно.

#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

Прежде всего, это не использует RegEx для очистки сайта (потому что у меня нет времени проверять это на всех комиксах), а использует API Internet Explorer для итерации по imgтегам DOM, пока не найдет тег с текстом заголовка.

Двоичный поток считывается из URL-адреса изображения и отображается в растровое изображение с помощью GDIPlus. Затем он отображается в симпатичном графическом интерфейсе с авторазмером и реальной всплывающей подсказкой, чтобы он работал почти так же, как веб-сайт.

Вот контрольный пример ( _(859)):

)


4
Было бы лучше, если бы вы добавили скобку обратно в изображение.
Мэтт

Ничего себе, только что узнал, что я могу запустить AutoIt под Wine на Ubuntu. Теперь все, что мне нужно сделать, это заставить IE работать там. На второй мысли ... +1 за ответ
ElPedro

2
@ElPedro Если у вас современный процессор, вместо вина используйте qemu KVM и seamlessRDP (в основном, DIY-параллели для linux). Это позволяет легко интегрировать приложения Windows в рабочий стол Linux и обеспечивает 100% совместимость + пропускную способность графического процессора. Просто совет.
mynxomaτ

Спасибо @ Mınxomaτ. Я могу попробовать. Я работаю с Windows весь день, поэтому предпочитаю использовать Linux (разные версии) без работы, но мне всегда интересно экспериментировать :) С благодарностью получили совет.
ElPedro

7

Powershell, 93 байта

93-байтовая версия для использования локальной программы просмотра изображений.

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

Сохраняя 2 байта, удаляя ненужные двойные кавычки, затем используйте другой лот ("http:"+$n.src)вместо "https://"+$n.src.trim("/")- поскольку imgsrc //уже включен , и xkcd не требует 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("/"))

очень похож на ответ Мэттса PowerShell (вероятно, это должен быть комментарий, но низкая репутация)

Вместо этого это открывает новую вкладку / окно в браузере по умолчанию и другие вещи, сохраняя некоторые байты.

iwr это псевдоним для Invoke-WebRequest

sapsэто псевдоним, для Start-Processкоторого открывается «это» в контексте по умолчанию.


Обход границ правил открытия существующей веб-страницы, потому что это просто прямой запуск браузера с уже существующим .jpg (или любым другим), но хороший ответ.
AdmBorkBork

Тогда @TimmyD, возможно, здесь неправильно поняли - я предположил, что вы можете использовать саму веб-страницу xkcd - вы можете просто изменить sapsее iwrи добавить `-OutF x.jpg; ii x. *` До конца, если вы хотите, чтобы она открывалась в локальной папке по умолчанию просмотрщик изображений.
colsw

1
ОП указал, что вы не можете открыть ранее существующую веб-страницу. 93-байтовая версия, я думаю, что все в порядке
спагетто

Я не думаю, что это всегда будет работать одинаково, если вы дадите число, которое работает, то число, которое не работает. Откроется изображение, существовавшее с предыдущего запуска.
Мэтт

Я принимаю 93-байтовую версию, но ваша более короткая нарушает условия головоломки.
Павел

4

R 358 328 310 298 байт

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

С новыми строками и комментариями:

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
}

Скриншоты тестовых случаев:

для х = 1500: для х = 1500 (png)

для х пусто:
для х = ''

случай, когда изображение в формате JPEG:
для х = 10 (JPEG)

х = 859:
х = 859


Интересно, нужно ли отображать изображение в правильных размерах. Когда я играл с этим вызовом, я просто сделал plot.new();rasterImage(...).
Billywob

@Billywob Ну, это было бы полностью искажено, поскольку размер по умолчанию для сюжета составляет 7x7 дюймов. Это правда, что ОП явно не просил, чтобы изображение не искажалось, но я предпочитаю это таким образом :) Я, однако, обдумываю избавиться от, xaxsи yaxsв результате все равно будет пропорциональным.
plannapus


2

Python 2,7, 309 299 295 274 байта

Полная программа. Определенно более пригодный для игры в гольф, но, прочитав комиксы xkcd так долго, я не мог пропустить это (кто знает, поможет ли это в будущем для удобного просмотра xkcd).

Если вход не передан, получает текущий комикс. Если в качестве входных данных передан действительный комический номер, он получает этот комикс. Если введен неверный ввод (не число комиксов в допустимом диапазоне), выдается ошибка.

Любые предложения о том, как уменьшить количество байтов, приветствуются! Вернусь (и добавлю объяснения), когда у меня будет больше времени.

-10 байт благодаря @Dopapp

-21 байт благодаря @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]

1
Вы можете изменить try:...и except:...на try:n=...и except:n='', экономя всего 10 байтов
Даниэль

1
Почему у вас даже есть tryзаявление? В спецификации программы сказано, что вы всегда получите положительное целое число.
Каде

@Shebang также должен возвращать последний комикс, когда нет ввода. Я не смог справиться с этим делом без исключения ошибки ввода.
Иоанн

1
@Joannes Почему бы не использовать raw_input()? По умолчанию пользователь может нажать [Enter]и nв любом случае будет содержать пустую строку. Если вы удалите этот пробный блок, и t=u.urlopen(h+x+n).read() -> t=u.urlopen(h+x+raw_input()).read()получите его до 274 байтов.
Каде

Это больше не работает, поскольку используются URL-адреса изображений xkcd https. Тем не менее, он все еще действителен, потому что он работал во время публикации. Чтобы заставить это работать сейчас, измените строку 3, чтобы начать с h='https://'+1 байта.
Mego

2

PHP, 42 байта

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

Сохраните в файл и запустите его на выбранном веб-сервере.


1
Добро пожаловать в PPCG! Я не знаю PHP, но, кажется, нет части вашего кода, которая извлекает текст заголовка изображения?
Павел

1

JavaScript + HTML, 124 + 18 = 142 байта

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>

Решение кросс-происхождения благодаря ответу Кайидо здесь .

17 байтов ( //crossorigin.me/) могут быть сохранены, если прокси, необходимый для подключения к xkcd.com, может быть вычтен ( мета-пост об этом ).

Тестовый фрагмент

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>


1

Python 3 + запросы + PIL, 192 186 байт

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

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.