Написание небольшого, но гибкого HTTP-клиента - PullRequest
2 голосов
/ 19 ноября 2010

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

#!/usr/bin/perl
use Socket;
use HTML::Parse;

socket(SOCKH, PF_INET, SOCK_STREAM, getprotobyname('tcp')) || die $!;
connect(SOCKH,sockaddr_in(80,inet_aton('www.example.com'))) || die $!;

$old_fh = select(SOCKH);
$|=1;
select($old_fh);

print SOCKH "GET / HTTP/1.0\n\n";

while (<SOCKH>) {
    $response .= $_;
}

print parse_html($response)->format;

close(<SOCKH>);

Это просто быстрый клиент, который я скоро отредактирую для HTTP / 1.1, или, если у вас есть предложения, как улучшить его для соответствия, пожалуйста, поделитесь!

РЕДАКТИРОВАТЬ: Обновление моего кода с использованием LWP, как предложил Синан Унур:

#!/usr/bin/perl
use LWP::Simple;
use HTML::Parse;

$data = parse_html( get( 'www.example.com' ) )->format;
foreach $line ( $data ) {
    print $line; // or any other line-based operation
}

Ответы [ 7 ]

9 голосов
/ 19 ноября 2010

Perl имеет LWP . Я предлагаю вам использовать его.

2 голосов
/ 19 ноября 2010

Python имеет «батареи в комплекте»

Вам не нужно работать на уровне сокетов (хотя вы можете). Python имеет несколько высокоуровневых библиотек web / http, встроенных в его стандартную библиотеку.

например, в Python 2 вы можете использовать urllib2 :

import urllib2

response = urllib2.urlopen('http://www.example.com/')
html = response.read()

также проверьте httplib , для немного более низкого уровня доступа:

>>> import httplib
>>> conn = httplib.HTTPConnection("www.python.org")
>>> conn.request("GET", "/index.html")
>>> r1 = conn.getresponse()
>>> print r1.status, r1.reason
200 OK
>>> data1 = r1.read()
>>> conn.request("GET", "/parrot.spam")
>>> r2 = conn.getresponse()
>>> print r2.status, r2.reason
404 Not Found
>>> data2 = r2.read()
>>> conn.close()
2 голосов
/ 19 ноября 2010

Аналогично примеру @ Санты, только в Ruby:

require 'open-uri'
print open('http://www.example.com').read

Если вы хотите проанализировать содержимое, Ruby's Nokogiri gem - это круто. Он построен на основе libXML.

Доступно множество других гемов HTTP-клиентов, включая HTTParty и Typhoeus. HTTParty упрощает добавление в класс возможностей REST, а также возможность разбора JSON и XML. Typhoeus упрощает одновременное написание нескольких запросов для параллельных операций get /heads / whatevers.

1 голос
/ 19 ноября 2010

Я так понимаю, что вы на самом деле не хотите писать свой собственный http-клиент, а скорее скрипт, который выбирает что-то, используя http?

Другие упомянутые HTTP :: Lite и LWP :: Simple ..

Вот пример использования Mojo :: Client , из документов.

# Quick JSON request
my $trends = 'http://search.twitter.com/trends.json';
print $client->get($trends)->res->json->{trends}->[0]->{name};

# Extract data from HTML and XML resources
print $client->get('mojolicious.org')->res->dom->at('title')->text;

# Scrape the latest headlines from a news site
my $news = 'http://digg.com';
$client->max_redirects(3);
$client->get($news)->res->dom('h3 > a.story-title')->each(sub {
    print shift->text . "\n";
});

Крутой, но не самый зрелый из доступных модулей ..

1 голос
/ 19 ноября 2010

Множество примеров кажутся тривиальными, пока вы не начнете делать что-то тяжелое, например потоковую передачу гигабайт данных в обоих направлениях. Мой фаворит - ruby's net/http, который является частью каждой установки ruby.

Вот пример, который передает данные и оставляет соединение открытым, когда вы закончите для дополнительных запросов.

require 'net/http'

http = Net::HTTP.new('my.server.org')
http.start

req = Net::HTTP::Post.new('/path/to/huge/file')
req.basic_auth('user', 'pass')
req.content_length = File.size 'huge_input_file.txt'
req.body_stream = File.open('huge_input_file.txt', 'rb')

http.request(req){|res|
  File.open('huge_output_file.txt', 'wb'){|f|
    res.read_body {|chunk| f.write chunk}
  }
}

Perl не имеет ничего встроенного. Net::HTTP и LWP::UserAgent не являются частью ядра Perl. Некоторое время назад я нуждался в http-клиенте perl, который функционирует подобно приведенному выше примеру ruby, не завися от чего-либо от CPAN. Это заняло менее 200 строк, используя только IO::Socket::INET и syswrite / sysread (что устраняет большую часть бессмысленности сокетов нижнего уровня), и MIME::Base64 для аутентификации.

1 голос
/ 19 ноября 2010
#!/usr/bin/env python

import urllib

f = urllib.urlopen('http://www.example.com')
print f.read()
f.close()
0 голосов
/ 03 декабря 2010

Я не понимаю, какую возможную выгоду вы получите от любых ответов на такой вопрос, но я уступлю давлению со стороны сверстников. Поскольку вы, кажется, не беспокоитесь, какой язык использовать ...

Если вы хотите манипулировать им интересными способами:

<?php
$d=new DOMDocument();
$d->loadHTMLFile('http://www.example.com/');
...

Но чтобы просто вернуть страницу:

<?php
print file_get_contents('http://www.example.com/');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...