O menor navegador da Web do mundo

72

Histórico:

Você gosta do seu novo trabalho de programação em uma megaempresa. No entanto, você não tem permissão para navegar na Web, pois seu computador possui apenas uma CLI. Eles também executam varreduras nos discos rígidos de todos os funcionários, para que você não possa simplesmente baixar um grande navegador da CLI. Você decide criar um navegador de texto simples, o mais pequeno possível, para memorizá-lo e digitá-lo em um arquivo temporário todos os dias.

Desafio:

Sua tarefa é criar um navegador da web dentro de uma interface da linha de comandos. Deveria:

  • Adquira uma única URL via args ou stdin
  • Divida os componentes directorye hostda URL
  • Envie uma solicitação HTTP simples para o hostpara solicitar o referidodirectory
  • Imprimir o conteúdo de qualquer tag de <p>parágrafo</p>
  • E saia ou peça outra página

Mais informações:

Uma solicitação HTTP simples se parece com isso:

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

Enfatizando novas linhas enfatizadas.

Uma resposta típica é semelhante a:

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

Regras:

  • Ele só precisa funcionar na porta 80 (não é necessário SSL)
  • Você não pode usar o netcat
  • Qualquer que seja a linguagem de programação usada, apenas APIs TCP de baixo nível são permitidas (exceto netcat)
  • Você não pode usar a GUI, lembre-se, é uma CLI
  • Você não pode usar analisadores de HTML, exceto os incorporados (BeautifulSoup não é um incorporado)
  • Bônus!! Se o seu programa retornar e solicitar outro URL em vez de sair, -40 caracteres (desde que você não use recursão)
  • Não há programas de terceiros. Lembre-se, você não pode instalar nada.
  • , para que a menor contagem de bytes ganhe
O médico
fonte
7
Python,import webbrowser;webbrowser.open(url)
Azul
8
@muddyfish ler as regras
TheDoctor
4
Você pode fornecer uma página da Web de algum tipo para testar isso? É difícil encontrar lugares que usam <p>: P
a spaghetto
52
Temos permissão para analisar HTML usando regex ? ;-)
Trauma digital
3
A restrição para interfaces de soquete de baixo nível parece proibir as APIs de nível TCP da maioria dos idiomas que possuem APIs de nível TCP.
22416 Peter Taylor

Respostas:

63

Pure Bash (sem utilitários), 200 bytes - bônus 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

Eu acho que isso está de acordo com as especificações, embora , é claro , tenha cuidado com a análise de HTML usando regex Acho que a única coisa pior do que analisar o HTML usando o regex é analisar o HTML usando a correspondência de padrões de shell.

Agora isso lida com a <p>...</p>abrangência de várias linhas. Cada um <p>...</p>está em uma linha de saída separada:

$ 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>
$ 
Trauma Digital
fonte
35
Você precisa memorizar isso amanhã.
Conor O'Brien
14
+ ∞ para "analisar HTML usando correspondência de padrões shell"
SztupY
76
-1 porque seu avatar é uma mensagem subliminar #
TheDoctor
11
... você pode fazer conexões TCP a partir do Bash? Agora estou verdadeiramente aterrorizada!
MatemáticoOrchid
2
Nota: /dev/tcpé uma extensão opcional e pode não estar presente na sua compilação do bash. Você precisa compilar com --enable-net-redirectionsele.
Chris Baixo
21

PHP, 175 bytes (215-40 bónus) 227 229 239 202 216 186 bytes

Divirta-se navegando na Web:

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

Lê URLs de STDINcomo http://www.example.com/. Gera parágrafos separados por nova linha " \n".


Ungolfed

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

Primeira versão que suporta apenas um 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";

insira a descrição da imagem aqui


Editar% s

  • Como apontado nos comentários de Braintist , esqueci totalmente de incluir o caminho. Isso está resolvido agora, obrigado. Adicionado 30 bytes .
  • Salva 3 bytes redefinindo $c(mantém o conteúdo da página) com em $c=$i=parse_url(trim(fgets(STDIN)));vez de $c=''.
  • Economizou 12 bytes substituindo \npor novas linhas (5 bytes), um whileloop com for(2 bytes), colocando quase tudo nas expressões de for(2 bytes) e substituindo foreachpor join(3 bytes). Graças ao Blackhole .
  • Economizou 3 bytes substituindo fgetspor stream_get_contentsThanks to bwoebi .
  • Economizou 5 bytes removendo a reinicialização, $cpois não é mais necessário $c .
  • Economizou 1 byte removendo o modificador de padrão mdo Regex. Graças à manatwork
insertusernamehere
fonte
6
Relacionados: stackoverflow.com/a/1732454/4766556
um Spaghetto
11
@ briantist Oh cara, eu senti muita falta disso. : D Obrigado, está consertado agora.
insertusernamehere
11
Não suporto que o Perl supere o PHP, então não esqueça: whileé proibido quando jogar golfe ( forgeralmente é mais curto, mas nunca mais longo) e, para fazer uma nova linha, basta pressionar enter (1 byte em vez de 2 para \n)! Aqui está o seu código (não testado) um pouco mais golfe (227 bytes), com a nova linha substituída por :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
11
Não quero dizer "proibido" como "contra as regras", apenas quero dizer que isso não é útil, pois um forloop é sempre melhor do que um whileloop;).
Blackhole
11
@MichaelDibbets Na verdade, eu já fiz isso como está escrito na edição. Hum. Deixe-me ver. Haha, esqueci de copiar e contar o trecho final. Duh : D Coisas assim acontecem, se você atualizar seu código antes do café da manhã. Obrigado por apontar isso.
insertusernamehere
14

Perl, 132 bytes

Código de 155 bytes + 17 para -ln -MIO::Socket- 40 para solicitar continuamente URLs

Como na resposta do @ DigitalTrauma, regex que analisa HTML, deixe-me saber se isso não é aceitável. Não fica mais analisando URLs ... Veremos isso mais tarde ... No entanto, próximo ao Bash! Muito obrigado a @ Schwern por me salvar 59 (!) Bytes e a @ skmrx por corrigir o erro para permitir uma reivindicação do bônus!

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

Uso

$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>
Dom Hastings
fonte
Corrigi um bug e reduzi o código removendo a necessidade de declarar $ he $ p ou ter um caminho padrão. Também não requer mais um rastreamento / no host.
Schwern 27/10/2015
11
Nós somos os únicos a vencer agora. :)
Schwern 27/10/2015
Acho que terminei a noite. :)
Schwern 27/10/2015
Como o script solicita outro URL em vez de sair, você pode reivindicar -40 bytes adicionais
svsd 27/10/15
11
@DigitalTrauma, você está realmente correto! Eu reivindiquei o bônus graças ao skmrx que corrigiu meu erro com '$ /' e eu não estaria perto do seu se não fosse por Schwern!
Dom Hastings
13

PowerShell, 315294268262254 bytes

355 334 308 302 294 - 40 para solicitação

$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
}

Requer PowerShell v5

Todas as terminações de linha (incluindo as incorporadas na string) são apenas novas linhas \n(graças ao Blackhole ), que são totalmente suportadas pelo PowerShell (mas se você estiver testando, tenha cuidado; o ISE usa \r\n).

briantist
fonte
4
+1 para fazer meus deveres de administração de servidores aparecem muito mais produtivo
thanby
HTTP requer CRLF, não LF! [ HTTPSYNTAX ]
Escova de dentes
2
@toothbrush Ha! Ponto levado, mas a disposição de tolerância parece estar em pleno vigor. Claramente, esta tarefa é sobre o que funciona e não o que é correto (caso contrário, não estaríamos analisando HTML com regex e usando bibliotecas TCP de baixo nível em vez de bibliotecas existentes bem testadas).
Briantist
11
@briantist greenbytes.de/tech/webdav/rfc7230.html#rfc.section.3.5 diz que "um destinatário PODE reconhecer um único LF como um terminador de linha e ignorar qualquer CR anterior". Eu li isso como significando que a maioria dos servidores da Web o implementaria, e a pergunta definitivamente não diz que deve gerar solicitações corretas GET ... :)
Toothbrush
8

Script Groovy, 89 , 61 bytes

Lacete de volta para bónus 101- 40 = 61

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

Com apenas args, 89 bytes

this.args[0].toURL().text.findAll(/<p>(?s)(.*?)<\/p>/).each{println it[3..it.length()-5]}
Rnet
fonte
11
Groovy superou todos. Como deveria ser.
a spaghetto
11
@quartata Se continuar assim, será a primeira vez que isso acontecerá, então ...;) #
Geobits
11
"apenas APIs TCP de baixo nível são permitidas"
Digital Trauma
Sim, eu vou concordar com @DigitalTrauma que isso não está usando uma API TCP de baixo nível. As regras declaram que você deve dividir o host e o caminho por conta própria.
TheDoctor
6

Bash (pode estar enganando, mas parece estar dentro das regras) 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

Obrigado ao Digital Trauma.

Como não preciso dividir o URL, isso também funciona: 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
philcolbourn
fonte
8
Eu diria que a utilização deste conversor html2txt online é uma brecha padrão
Trauma Digital
11
Sim. E eu também uso gato para que sua solução seja segura.
philcolbourn
5

C 512 bytes

#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);}}} 

Baseado livremente na minha entrada aqui , é necessário o endereço da Web sem um "https: //" inicial. Ele não manipulará <p>pares aninhados corretamente :(

Testado extensivamente em www.w3.org/People/Berners-Lee/
Funciona quando compilado com Apple LLVM version 6.1.0 (clang-602.0.53) / Target: x86_64-apple-darwin14.1.1
Possui um comportamento indefinido suficiente para que não funcione em nenhum outro lugar.

AShelly
fonte
Eu estava descendo aproximadamente a mesma faixa (isso segfaults quando compilado com o gcc), mas deve ser possível obter menos de 400 bytes em C. Não tenho certeza sobre o clang, mas não é necessário declarar o tipo de retorno principal. Você também pode remover a inclusão e "acessar" as estruturas como matrizes inteiras. Também recebi respostas com "GET /% s HTTP / 1.1 \ r \ n \ r \ n \", mas a milhagem pode variar de acordo com o site ...
Comintern
5

Ruby, 118

Fonte de 147 bytes; 11 bytes ' -lprsocket'; -40 bytes para loop.

*_,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

Exemplo de uso:

$ 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>.
ezrast
fonte
4

AutoIt , 347 bytes

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

Testando

Entrada:

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

Resultado:

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

Entrada:

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

Resultado:

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

Observações

  • Não suporta <p>tags aninhadas
  • Suporta apenas <p>tags (sem distinção entre maiúsculas e minúsculas), será interrompido em qualquer outro formato de tag
  • Pânico Loops indefinidamente quando ocorre algum erro
mınxomaτ
fonte
4

C #, 727 bytes - 40 = 687 bytes

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;}}

É um pouco de treinamento, mas certamente memorável :)

Aqui está uma versão não destruída:

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;
        }
    }
}

Como você pode ver, há problemas de vazamento de memória como um bônus :)

Stephan Schinkel
fonte
Onde está o vazamento de memória? Não vejo usingdeclarações em torno de fluxos, mas isso não vaza.
Gusdor
Você pode aparar mais alguns bytes: input = input.trimStart ("http: //") substituirá a cláusula "if" e você poderá usar System.Text.Encoding.ASCII.GetBytes () diretamente sem ter para armazená-lo em asciiEncoding primeiro. Eu acho que você sairia na frente com um "Using System"; linha e se livrar de um punhado de "Sistema".
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))));

Uso:

node file.js www.example.com

Ou formatado

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)))
});
Benjamin Gruenbaum
fonte
11
Advertência: isso funcionará para páginas pequenas - páginas maiores emitem vários eventos de dados.
Benjamin Gruenbaum
3

Python 2 - 212 209 bytes

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
Zac Crites
fonte
Você pode salvar dois bytes removendo o espaço em branco após os dois pontos while h:antes e depois print g.
Skyler
E outro byte com 'GET /%s HTTP/1.1\nHost:%s\n\n'.
Cees Timmerman
3

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

Versão compactada e em loop da resposta de Zac :

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

Exemplo:

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

Realmente útil é o seguinte:

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

Exemplo:

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]
Cees Timmerman
fonte
1

gawk, 235 - 40 = 195 bytes

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

Golpeou, mas esta é uma versão mais implacável, que precisa do endereço da Web sem http://no começo. E se você quiser acessar o diretório raiz, precisará terminar o endereço com a /. Além disso, as <p>tags devem ser minúsculas.

Minha versão anterior, na verdade, não lidava com linhas contendo </p><p>corretamente. Agora está corrigido.

Saída para entrada 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>

Ainda não funciona com a Wikipedia. Eu acho que o motivo é que a Wikipedia usa httpspara tudo. Mas eu não sei.

A versão a seguir é um pouco mais tolerante com a entrada e também pode lidar com tags maiúsculas.

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

Eu não tenho certeza sobre a "Connection:close"linha. Não parece ser obrigatório. Não consegui encontrar um exemplo que funcionasse diferente com ou sem ele.

Cabbie407
fonte
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 (proxy não é necessário)

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

editar * também não é difícil de memorizar ^^

dwana
fonte
-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) {

        }
    }

}
Shalika Ashan
fonte
2
Bem-vindo à programação de quebra-cabeças e código de golfe! Infelizmente, este envio é inválido. A pergunta permite apenas APIs TCP de baixo nível, portanto você não pode usá-lo InputStreamReader.
Dennis
11
Oh, sinto muito e obrigado por apontá-lo. fará melhor na próxima resposta
Shalika Ashan