Найменший веб-браузер у світі


72

Посилання:

Ви насолоджуєтесь своєю новою роботою з програмування в мега-мультикорпорації. Однак ви не можете переглядати Інтернет, оскільки на вашому комп'ютері є лише CLI. Вони також виконують обчислення жорстких дисків усіх працівників, тому ви не можете просто завантажити великий веб-браузер CLI. Ви вирішили зробити простий текстовий браузер, який є якомога меншим, щоб ви могли запам'ятати його і вводити його у тимчасовий файл щодня.

Виклик:

Ваше завдання - створити веб-браузер для гольфу в інтерфейсі командного рядка. Слід:

  • Візьміть одну URL-адресу через args або stdin
  • Розділіть directoryі hostкомпоненти URL-адреси
  • Надішліть простий HTTP-запит hostна запит зазначеногоdirectory
  • Роздрукуйте вміст будь-яких тегів <p>абзацу</p>
  • І або вийдіть, або попросіть іншу сторінку

Більше інформації:

Простий запит HTTP виглядає приблизно так:

GET {{path}} HTTP/1.1
Host: {{host}}
Connection: close
\n\n

Підкреслюється закінчення нових рядків.

Типова відповідь виглядає так:

HTTP/1.1 200 OK\n
<some headers separated by newlines>
\n\n
<html>
....rest of page

Правила:

  • Потрібно працювати лише на порту 80 (не потрібен SSL)
  • Ви не можете використовувати netcat
  • Яку б мову програмування не використовували, дозволені лише API TCP низького рівня (крім netcat)
  • Ви не можете використовувати GUI, пам’ятайте, що це CLI
  • Ви не можете використовувати HTML-парсери, крім вбудованих (BeautifulSoup не є вбудованим)
  • Бонус !! Якщо ваша програма повертається назад і запитує іншу URL-адресу замість виходу, -40 символів (якщо ви не використовуєте рекурсію)
  • Жодних сторонніх програм немає. Пам'ятайте, ви нічого не можете встановити.
  • , тому виграє найменший кількість байтів

7
Python,import webbrowser;webbrowser.open(url)
Синій

8
@muddyfish читав правила
TheDoctor

4
Чи можете ви надати зразок якоїсь веб-сторінки для тестування цього? Важко знайти місця, які використовують <p>: P
спагето


3
Обмеження на низькорівневі інтерфейси сокетів, здається, забороняє API рівня TCP більшості мов, які мають API рівня TCP.
Пітер Тейлор

Відповіді:


63

Pure Bash (без комунальних послуг), 200 байт - 40 бонусів = 160

while read u;do
u=${u#*//}
d=${u%%/*}
exec 3<>/dev/tcp/$d/80
echo "GET /${u#*/} HTTP/1.1
host:$d
Connection:close
">&3
mapfile -tu3 A
a=${A[@]}
a=${a#*<p>}
a=${a%</p>*}
echo "${a//<\/p>*<p>/"
"}"
done

Я думаю, що це залежить від специфікації, хоча, звичайно, слідкуйте за розбором HTML за допомогою regex. Я думаю, що єдине гірше, ніж розбирати HTML за допомогою regex, - це розбирати HTML, використовуючи відповідність шаблону оболонки.

Зараз це стосується <p>...</p>декількох ліній. Кожен <p>...</p>знаходиться в окремому рядку виводу:

$ echo "http://example.com/" | ./smallbrowse.sh
This domain is established to be used for illustrative examples in documents. You may use this     domain in examples without prior coordination or asking for permission.
<a href="http://www.iana.org/domains/example">More information...</a>
$ 

35
Це потрібно запам'ятати до завтра.
Conor O'Brien

14
+ ∞ для "розбору HTML за допомогою відповідності шаблону оболонки"
SztupY

76
-1 тому що ваш аватар - це підсвідоме повідомлення
TheDoctor

1
... ви можете встановити TCP-з'єднання з Bash? Тепер я справді жахнувся!
Математична

2
Примітка: /dev/tcpце необов'язкове розширення і може не бути у вашій збірці bash. Вам потрібно скласти, --enable-net-redirectionsщоб мати його.
Кріс Даун

21

PHP, 175 байт (215 - 40 бонусів) 227 229 239 202 216 186 байт

Приємно переглядайте Інтернет:

for(;$i=parse_url(trim(fgets(STDIN))),fwrite($f=fsockopen($h=$i[host],80),"GET $i[path] HTTP/1.1
Host:$h
Connection:Close

");preg_match_all('!<p>(.+?)</p>!si',stream_get_contents($f),$r),print join("
",$r[1])."
");

Читає URL-адреси з STDINподібних http://www.example.com/. Виводи абзаци, розділені новим рядком " \n".


Безумовно

for(; $i=parse_url(trim(fgets(STDIN))); ) {
    $h = $i['host'];
    $f = fsockopen($h, 80);

    fwrite($f, "GET " . $i['path'] . " HTTP/1.1\nHost:" . $h . "\nConnection:Close\n\n");

    $c = stream_get_contents($f)

    preg_match_all('!<p>(.+?)</p>!si', $c, $r);
    echo join("\n", $r[1]) . "\n";
}

Перша версія, що підтримує лише одну URL-адресу

$i=parse_url($argv[1]);fwrite($f=fsockopen($h=$i[host],80),"GET $i[path] HTTP/1.1\nHost:$h\nConnection:Close\n\n");while(!feof($f))$c.=fgets($f);preg_match_all('!<p>(.+?)</p>!sim',$c,$r);foreach($r[1]as$p)echo"$p\n";

введіть тут опис зображення


Правки

  • Як вказувалося в коментарях Braintist , я повністю забув включити шлях. Це все виправлено, спасибі. Додано 30 байт .
  • Збережено 3 байти шляхом скидання $c(містить вміст сторінки) за допомогою, $c=$i=parse_url(trim(fgets(STDIN)));а не $c=''.
  • Збережено 12 байтів , замінивши \nнові рядки (5 байт), один - whileпетлю for(2 байти), розмістивши майже все в виразах for(2 байти) та замінивши foreachна join(3 байти). Завдяки Blackhole .
  • Збережено 3 байта , замінивши fgetsз stream_get_contentsЗавдяки bwoebi .
  • Збережено 5 байт , видаливши повторну ініціалізацію, $cоскільки вона взагалі більше не потрібна $c .
  • Збережено 1 байт , видаливши модифікатор шаблону mз Regex. Завдяки маневреності


1
@briantist О людино, я це зовсім пропустив. : D Спасибі, це зараз виправлено.
insertusernamehere

1
Я не можу терпіти, що Perl б'є PHP, тому не забувайте: whileзаборонено при гольфі ( forчасто коротше, але ніколи більше), а для того, щоб робити новий рядок, просто натисніть клавішу Enter (1 байт замість 2 для \n)! Ось ваш (неперевірений) код трохи більше гольфу (227 байт), причому новий рядок замінено на :for(;$c=$i=parse_url(trim(fgets(STDIN))),fwrite($f=fsockopen($h=$i[host],80),"GET $i[path] HTTP/1.1↵Host:$h↵Connection:Close↵↵");preg_match_all('!<p>(.+?)</p>!sim',$c,$r),print join('↵',$r[1]).'↵')for(;!feof($f);)$c.=fgets($f);
Blackhole

1
Я не маю на увазі "заборонено", як "проти правил", я просто маю на увазі, що це зовсім не корисно, оскільки for-loop завжди кращий, ніж while-loop;).
Blackhole

1
@MichaelDibbets Насправді я це зробив уже так, як написано в редакції. Гм. Дозвольте мені побачити. Ха-ха, я забув скопіювати та порахувати остаточний фрагмент. Дух : D Такі речі трапляються, якщо ви оновите код перед сніданком. Дякуємо, що вказали на це.
insertusernamehere

14

Perl, 132 байти

Код 155 байт + 17 для -ln -MIO::Socket- 40 для постійного запиту URL-адрес

Як і у відповіді @ DigitalTrauma, при розборі HTML-підробок, повідомте мене, якщо це не прийнятно. Більше не продовжує розбирати URL-адреси ... Я розгляну це пізніше ... Близько до Bash! Велика подяка @ Schwern за те, що врятував мені 59 (!) Байтів, і @ skmrx за виправлення помилки, щоб дозволити претензію на преміювання!

m|(http://)?([^/]+)(/(\S*))?|;$s=new IO::Socket::INET"$2:80";print$s "GET /$4 HTTP/1.1
Host:$2
Connection:close

";local$/=$,;print<$s>=~m|<p>(.+?)</p>|gs

Використання

$perl -ln -MIO::Socket -M5.010 wb.pl 
example.com
This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.<a href="http://www.iana.org/domains/example">More information...</a>
example.org
This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.<a href="http://www.iana.org/domains/example">More information...</a>

Я виправив помилку і скоротив код, усунувши необхідність оголошувати $ h і $ p або мати шлях за замовчуванням. Він також більше не вимагає завершення / на хості.
Шверн

1
Зараз ми маємо бити. :)
Schwern

Я думаю, що я закінчив на ніч. :)
Шверн

Оскільки сценарій запитує іншу URL-адресу замість виходу, ви можете вимагати додаткових -40 байт
svsd

1
@DigitalTrauma ви справді правильні! Я вимагав бонусу завдяки skmrx, який виправляв мою помилку з '$ /', і я не був би поруч із вашою, якби не Шверн!
Дом Гастінгс

13

PowerShell, 315 294 268 262 254 байт

355 334 308 302 294 - 40 для оперативного

$u=[uri]$args[0]
for(){
$h=$u.Host
$s=[Net.Sockets.TcpClient]::new($h,80).GetStream()
$r=[IO.StreamReader]::new($s)
$w=[IO.StreamWriter]::new($s)
$w.Write("GET $($u.PathAndQuery) HTTP/1.1
HOST: $h

")
$w.Flush()
($r.ReadToEnd()|sls '(?s)(?<=<p>).+?(?=</p>)'-a).Matches.Value
[uri]$u=Read-Host
}

Потрібна PowerShell v5

Всі закінчення рядків (включаючи вбудовані в рядок) - це лише нові рядки \n(дякую Blackhole ), які повністю підтримуються PowerShell (але якщо ви тестуєте, будьте обережні; ISE використовує \r\n).


4
+1 за те, щоб обов'язки мого сервера виглядали набагато продуктивнішими
ніж

HTTP вимагає CRLF, а не LF! [ HTTPSYNTAX ]
Зубна щітка

2
@toothbrush Ha! Точка прийнята, але положення про толерантність, здається, в повній мірі. Зрозуміло, що це завдання полягає в тому, що працює, а не те, що правильно (інакше ми б не розбирали HTML за допомогою регулярного вираження та використовували бібліотеки низького рівня TCP замість добре перевірених існуючих бібліотек).
брианіст

1
@briantist greenbytes.de/tech/webdav/rfc7230.html#rfc.section.3.5 говорить, що "одержувач МОЖЕ розпізнати один LF як термінальний рядок і ігнорувати будь-який попередній CR". Я читав, що в сенсі більшість веб-серверів реалізують це, і питання, безумовно, не говорить про те, що він повинен генерувати правильні GET запити… :)
Зубна щітка

8

Groovy скрипт, 89 , 61 байт

Зверніть петлю на бонус 101- 40 = 61

System.in.eachLine{l->l.toURL().text.findAll(/<p>(?s)(.*?)<\/p>/).each{println it[3..it.length()-5]}}

З просто аргументами, 89 байт

this.args[0].toURL().text.findAll(/<p>(?s)(.*?)<\/p>/).each{println it[3..it.length()-5]}

1
Groovy перевершив усіх. Як має бути.
спагетто

1
@quartata Якщо так буде, то це буде вперше , тому ...;)
Geobits

11
"дозволені лише API TCP низького рівня"
Digital Trauma

Так, я погоджуся з @DigitalTrauma, що це не використовується API низького рівня TCP. У правилах зазначено, що ви повинні розділити хост і шлях самостійно.
TheDoctor

6

Баш (може бути шахрайством, але, здається, в межах правил) 144-40 = 105

while read a;do
u=${a#*//}
d=${u%%/*}
e=www.w3.org
exec 3<>/dev/tcp/$d/80
echo "GET /services/html2txt?url=$a HTTP/1.1
Host:$d
">&3
cat <&3
done

Завдяки цифровій травмі.

Оскільки мені не потрібно ділити URL, це також працює: 122-40 = 82

while read a;do
d=www.w3.org
exec 3<>/dev/tcp/$d/80
echo "GET /services/html2txt?url=$a HTTP/1.1
Host:$d
">&3   
cat <&3
done

8
Я б заперечував, що використання цього інтернет-перетворювача html2txt є стандартною лазівкою
Digital Trauma

1
Так. І я також використовую кішку, щоб ваше рішення було безпечним.
philcolbourn

5

C 512 байт

#include <netdb.h>
int main(){char i,S[999],b[99],*p,s=socket(2,1,0),*m[]={"<p>","</p>"};long n;
gets(S);p=strchr(S,'/');*p++=0;struct sockaddr_in a={0,2,5<<12};memcpy(&a.
sin_addr,gethostbyname(S)->h_addr,4);connect(s,&a,16);send(s,b,sprintf(b,
"GET /%s HTTP/1.0\r\nHost:%s\r\nAccept:*/*\r\nConnection:close\r\n\r\n",p,S),0);
p=m[i=0];while((n=recv(s,b,98,0))>0)for(char*c=b;c<b+n;c++){while(*c==*p &&*++p)
c++;if(!*p)p=m[(i=!i)||puts("")];else{while(p>m[i]){if(i)putchar(c[m[i]-p]);p--;}
if(i)putchar(*c);}}} 

Грунтуючись на моєму введенні тут , він займає веб-адресу без провідного "https: //". Він не буде обробляти вкладені <p>пари правильно :(

Тестовано випробування на www.w3.org/People/Berners-Lee/
Він працює при компіляції з ним Apple LLVM version 6.1.0 (clang-602.0.53) / Target: x86_64-apple-darwin14.1.1
має достатньо невизначеного поведінки, щоб він більше не працював.


Я йшов приблизно по тому ж доріжці (це segfaults, коли компілюється з gcc), але слід отримати можливість отримати менше 400 байт в C. Не впевнений у кланге, але не потрібно було оголошувати тип повернення main. Ви також можете вилучити структури include і "отримати доступ" до них як цілі масиви. Я також отримував відповіді з "GET /% s HTTP / 1.1 \ r \ n \ r \ n \", але пробіг на це може змінюватись залежно від сайту ...
Комінтерн

5

Рубі, 118

147 байт джерела; 11 байт ' -lprsocket'; -40 байт для циклу.

*_,h,p=$_.split'/',4
$_=(TCPSocket.new(h,80)<<"GET /#{p} HTTP/1.1
Host:#{h}
Connection:close

").read.gsub(/((\A|<\/p>).*?)?(<p>|\Z)/mi,'
').strip

Приклад використання:

$ ruby -lprsocket wb.rb
http://example.org/
This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.
<a href="http://www.iana.org/domains/example">More information...</a>
http://www.xkcd.com/1596/
Warning: this comic occasionally contains strong language (which may be unsuitable for children), unusual humor (which may be unsuitable for adults), and advanced mathematics (which may be unsuitable for liberal-arts majors).

This work is licensed under a
<a href="http://creativecommons.org/licenses/by-nc/2.5/">Creative Commons Attribution-NonCommercial 2.5 License</a>.


This means you're free to copy and share these comics (but not to sell them). <a rel="license" href="/license.html">More details</a>.

4

AutoIt , 347 байт

Func _($0)
$4=StringTrimLeft
$0=$4($0,7)
$3=StringSplit($0,"/")[1]
TCPStartup()
$2=TCPConnect(TCPNameToIP($3),80)
TCPSend($2,'GET /'&$4($0,StringLen($3))&' HTTP/1.1'&@LF&'Host: '&$3&@LF&'Connection: close'&@LF&@LF)
$1=''
Do
$1&=TCPRecv($2,1)
Until @extended
For $5 In StringRegExp($1,"(?s)\Q<p>\E(.*?)(?=\Q</p>\E)",3)
ConsoleWrite($5)
Next
EndFunc

Тестування

Вхід:

_('http://www.autoitscript.com')

Вихід:

You don't have permission to access /error/noindex.html
on this server.

Вхід:

_('http://www.autoitscript.com/site')

Вихід:

The document has moved <a href="https://www.autoitscript.com/site">here</a>.

Зауваження

  • Не підтримує вкладені <p>теги
  • Підтримує лише <p>теги (нечутливі до регістру), вони перериваються на всі інші формати тегів
  • Паніка панікує нескінченно, коли виникає будь-яка помилка

4

C #, 727 байт - 40 = 687 байт

using System.Text.RegularExpressions;class P{static void Main(){a:var i=System.Console.ReadLine();if(i.StartsWith("http://"))i=i.Substring(7);string p="/",h=i;var l=i.IndexOf(p);
if(l>0){h=i.Substring(0,l);p=i.Substring(l,i.Length-l);}var c=new System.Net.Sockets.TcpClient(h,80);var e=System.Text.Encoding.ASCII;var d=e.GetBytes("GET "+p+@" HTTP/1.1
Host: "+h+@"
Connection: close

");var s=c.GetStream();s.Write(d,0,d.Length);byte[]b=new byte[256],o;var m=new System.IO.MemoryStream();while(true){var r=s.Read(b,0,b.Length);if(r<=0){o=m.ToArray();break;}m.Write(b,0,r);}foreach (Match x in new Regex("<p>(.+?)</p>",RegexOptions.Singleline).Matches(e.GetString(o)))System.Console.WriteLine(x.Groups[1].Value);goto a;}}

Це трохи тренувань, але напевно запам'ятовується :)

Ось незворушена версія:

using System.Text.RegularExpressions;
class P
{
    static void Main()
    {
    a:
        var input = System.Console.ReadLine();
        if (input.StartsWith("http://")) input = input.Substring(7);
        string path = "/", hostname = input;
        var firstSlashIndex = input.IndexOf(path);
        if (firstSlashIndex > 0)
        {
            hostname = input.Substring(0, firstSlashIndex);
            path = input.Substring(firstSlashIndex, input.Length - firstSlashIndex);
        }
        var tcpClient = new System.Net.Sockets.TcpClient(hostname, 80);
        var asciiEncoding = System.Text.Encoding.ASCII;
        var dataToSend = asciiEncoding.GetBytes("GET " + path + @" HTTP/1.1
Host: " + hostname + @"
Connection: close

");
        var stream = tcpClient.GetStream();
        stream.Write(dataToSend, 0, dataToSend.Length);
        byte[] buff = new byte[256], output;
        var ms = new System.IO.MemoryStream();
        while (true)
        {
            var numberOfBytesRead = stream.Read(buff, 0, buff.Length);
            if (numberOfBytesRead <= 0)
            {
                output = ms.ToArray();
                break;
            }
            ms.Write(buff, 0, numberOfBytesRead);
        }
        foreach (Match match in new Regex("<p>(.+?)</p>", RegexOptions.Singleline).Matches(asciiEncoding.GetString(output)))
        {
            System.Console.WriteLine(match.Groups[1].Value);
            goto a;
        }
    }
}

Як бачите, проблеми з витоком пам’яті є бонусом :)


Де протікає пам'ять? Я не бачу жодних usingзаяв навколо потоків, але це не протікає.
Гусдор

Ви можете обрізати ще кілька байтів: input = input.trimStart ("http: //") замінить пункт "якщо", і ви зможете використовувати System.Text.Encoding.ASCII.GetBytes () безпосередньо, не маючи щоб спочатку зберегти його в asciiEncoding Я думаю, ти навіть вийдеш наперед із "Використанням системи"; лінії та позбавлення від жменьки "Системи".
minnmass

3

JavaScript (NodeJS) - 187 166

s=require("net").connect(80,p=process.argv[2],_=>s.write("GET / HTTP/1.0\nHost: "+p+"\n\n")&s.on("data",d=>(d+"").replace(/<p>([^]+?)<\/p>/g,(_,g)=>console.log(g))));

187:

s=require("net").connect(80,p=process.argv[2],_=>s.write("GET / HTTP/1.1\nHost: "+p+"\nConnection: close\n\n")&s.on("data",d=>(d+"").replace(/<p>([^]+?)<\/p>/gm,(_,g)=>console.log(g))));

Використання:

node file.js www.example.com

Або відформатовано

var url = process.argv[2];
s=require("net").connect(80, url ,_=> {
     s.write("GET / HTTP/1.1\nHost: "+url+"\nConnection: close\n\n");
     s.on("data",d=>(d+"").replace(/<p>([^]+?)<\/p>/gm,(_,g)=>console.log(g)))
});

1
Caveat: це буде працювати для невеликих сторінок - більші сторінки випромінюють декілька подій даних.
Бенджамін Грюнбаум

3

Python 2 - 212 209 байт

import socket,re
h,_,d=raw_input().partition('/')
s=socket.create_connection((h,80))
s.sendall('GET /%s HTTP/1.1\nHost:%s\n\n'%(d,h))
p=''
while h:h=s.recv(9);p+=h
for g in re.findall('<p>(.*?)</p>',p):print g

Ви можете зберегти два байти, викресливши пробіл після двокрапки while h:та раніше print g.
Skyler

І ще один байт с 'GET /%s HTTP/1.1\nHost:%s\n\n'.
Cees Timmerman

3

Python 2, 187 - 40 = 147 (141 в REPL)

Стислий і петельний варіант відповіді Зака :

import socket,re
while 1:h,_,d=raw_input().partition('/');s=socket.create_connection((h,80));s.sendall('GET /%s HTTP/1.1\nHost:%s\n\n'%(d,h));print re.findall('<p>(.*?)</p>',s.recv(9000))

Приклад:

dictionary.com
['The document has moved <a href="http://dictionary.reference.com/">here</a>.']
dictionary.reference.com
[]
paragraph.com
[]
rare.com
[]

Насправді корисно це:

207 - 40 = 167

import socket,re
while 1:h,_,d=raw_input().partition('/');s=socket.create_connection((h,80));s.sendall('GET /%s HTTP/1.1\nHost:%s\n\n'%(d,h));print'\n'.join(re.findall('<p>(.*?)</p>',s.recv(9000),re.DOTALL))

Приклад:

example.org
This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.
<a href="http://www.iana.org/domains/example">More information...</a>
www.iana.org/domains/example
The document has moved <a href="/domains/reserved">here</a>.
www.iana.org/domains/reserved

dictionary.com
The document has moved <a href="http://dictionary.reference.com/">here</a>.
dictionary.reference.com

catb.org

      <a href="http://validator.w3.org/check/referer"><img
          src="http://www.w3.org/Icons/valid-xhtml10"
          alt="Valid XHTML 1.0!" height="31" width="88" /></a>

This is catb.org, named after (the) Cathedral and the Bazaar. Most
of it, under directory esr, is my personal site.  In theory other
people could shelter here as well, but this has yet to occur.
catb.org/jargon
The document has moved <a href="http://www.catb.org/jargon/">here</a>.
www.catb.org/jargon/
This page indexes all the WWW resources associated with the Jargon File
and its print version, <cite>The New Hacker's Dictionary</cite>. It's as
official as anything associated with the Jargon File gets.
On 23 October 2003, the Jargon File achieved the
dubious honor of being cited in the SCO-vs.-IBM lawsuit.  See the <a
href='html/F/FUD.html'>FUD</a> entry for details.
www.catb.org/jargon/html/F/FUD.html
 Defined by Gene Amdahl after he left IBM to found his own company:
   &#8220;<span class="quote">FUD is the fear, uncertainty, and doubt that IBM sales people
   instill in the minds of potential customers who might be considering
   [Amdahl] products.</span>&#8221; The idea, of course, was to persuade them to go
   with safe IBM gear rather than with competitors' equipment.  This implicit
   coercion was traditionally accomplished by promising that Good Things would
   happen to people who stuck with IBM, but Dark Shadows loomed over the
   future of competitors' equipment or software.  See
   <a href="../I/IBM.html"><i class="glossterm">IBM</i></a>.  After 1990 the term FUD was associated
   increasingly frequently with <a href="../M/Microsoft.html"><i class="glossterm">Microsoft</i></a>, and has
   become generalized to refer to any kind of disinformation used as a
   competitive weapon.
[In 2003, SCO sued IBM in an action which, among other things,
   alleged SCO's proprietary control of <a href="../L/Linux.html"><i class="glossterm">Linux</i></a>.  The SCO
   suit rapidly became infamous for the number and magnitude of falsehoods
   alleged in SCO's filings.  In October 2003, SCO's lawyers filed a <a href="http://www.groklaw.net/article.php?story=20031024191141102" target="_top">memorandum</a>
   in which they actually had the temerity to link to the web version of
   <span class="emphasis"><em>this entry</em></span> in furtherance of their claims. Whilst we
   appreciate the compliment of being treated as an authority, we can return
   it only by observing that SCO has become a nest of liars and thieves
   compared to which IBM at its historic worst looked positively
   angelic. Any judge or law clerk reading this should surf through to
   <a href="http://www.catb.org/~esr/sco.html" target="_top">my collected resources</a> on this
   topic for the appalling details.&#8212;ESR]

1

gawk, 235 - 40 = 195 байт

{for(print"GET "substr($0,j)" HTTP/1.1\nHost:"h"\n"|&(x="/inet/tcp/0/"(h=substr($0,1,(j=index($0,"/"))-1))"/80");(x|&getline)>0;)w=w RS$0
for(;o=index(w,"<p>");w=substr(w,c))print substr(w=substr(w,o+3),1,c=index(w,"/p>")-2)
close(x)}

Завантажили його, але це більш невблаганна версія, для якої потрібна веб-адреса без http://початку. І якщо ви хочете отримати доступ до кореневого каталогу, вам потрібно закінчити адресу /. Крім того, <p>теги повинні бути малі.

Моя попередня версія насправді не обробляла лінії, що містять </p><p>правильно. Це зараз виправлено.

Вихід для введення example.com/

This domain is established to be used for illustrative examples in documents. You may use this
    domain in examples without prior coordination or asking for permission.
<a href="http://www.iana.org/domains/example">More information...</a>

Досі не працює з Вікіпедією. Я думаю, що причина полягає в тому, що Вікіпедія використовує httpsдля всього. Але я не знаю.

Наступна версія трохи прощає вхід, і вона також може обробляти верхні регістри тегів.

IGNORECASE=1{
    s=substr($0,(i=index($0,"//"))?i+2:0)
    x="/inet/tcp/0/"(h=(j=index(s,"/"))?substr(s,1,j-1):s)"/80"
    print"GET "substr(s,j)" HTTP/1.1\nHost:"h"\nConnection:close\n"|&x
    while((x|&getline)>0)w=w RS$0
    for(;o=index(w,"<p>");w=substr(w,c))
        print substr(w=substr(w,o+3),1,c=index(w,"/p>")-2)
    close(x)
}

Я не впевнений у "Connection:close"лінії. Це не здається обов'язковим. Я не міг знайти приклад, який би працював по-різному з ним чи без нього.


1

Powershell (4) 240

$input=Read-Host ""
$url=[uri]$input
$dir=$url.LocalPath
Do{
$res=Invoke-WebRequest -URI($url.Host+"/"+$dir) -Method Get
$res.ParsedHtml.getElementsByTagName('p')|foreach-object{write-host $_.innerText}
$dir=Read-Host ""
}While($dir -NE "")

Ungolfed (проксі не потрібно)

$system_proxyUri=Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyServer
$proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$proxyUri = $proxy.GetProxy($system_proxyUri.ProxyServer)
$input = Read-Host "Initial url"
#$input="http://stackoverflow.com/questions/tagged/powershell"
$url=[uri]$input
$dir=$url.LocalPath
Do{
$res=Invoke-WebRequest -URI($url.Host+"/"+$dir) -Method Get -Proxy($proxyUri)
$res.ParsedHtml.getElementsByTagName('p')|foreach-object{write-host $_.innerText}
$dir=Read-Host "next dir"
}While($dir -NE "")

редагувати * також не важко запам’ятовувати ^^


-1

Java 620 B

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

public class JavaApplication12 {

    public static void main(String[] args) {
        try {             
            BufferedReader i = new BufferedReader(new InputStreamReader(new URL(args[0]).openStream()));
            String l;
            boolean print = false;
            while ((l = i.readLine()) != null) {
                if (l.toLowerCase().contains("<p>")) {
                    print = true;
                }
                if (print) {
                    if (l.toLowerCase().contains("</p>")) {
                        print = false;
                    }
                    System.out.println(l);
                }
            }

        } catch (Exception e) {

        }
    }

}

2
Ласкаво просимо до головоломки програмування та коду для гольфу! На жаль, це подання недійсне. Питання дозволяє лише API низького рівня TCP, тому ви не можете користуватися InputStreamReader.
Денніс

1
О, мені так шкода і дякую, що вказали на це. краще піде в наступній відповіді
Шаліка Ашан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.