Страуструп недавно опубликовал серию публикаций, разоблачающих популярные мифы о C ++ . Пятый миф: «C ++ предназначен только для больших, сложных программ». Чтобы разоблачить его, он написал простую программу на C ++, загружающую веб-страницу и извлекающую из нее ссылки . Вот:
#include <string>
#include <set>
#include <iostream>
#include <sstream>
#include <regex>
#include <boost/asio.hpp>
using namespace std;
set<string> get_strings(istream& is, regex pat)
{
set<string> res;
smatch m;
for (string s; getline(is, s);) // read a line
if (regex_search(s, m, pat))
res.insert(m[0]); // save match in set
return res;
}
void connect_to_file(iostream& s, const string& server, const string& file)
// open a connection to server and open an attach file to s
// skip headers
{
if (!s)
throw runtime_error{ "can't connect\n" };
// Request to read the file from the server:
s << "GET " << "http://" + server + "/" + file << " HTTP/1.0\r\n";
s << "Host: " << server << "\r\n";
s << "Accept: */*\r\n";
s << "Connection: close\r\n\r\n";
// Check that the response is OK:
string http_version;
unsigned int status_code;
s >> http_version >> status_code;
string status_message;
getline(s, status_message);
if (!s || http_version.substr(0, 5) != "HTTP/")
throw runtime_error{ "Invalid response\n" };
if (status_code != 200)
throw runtime_error{ "Response returned with status code" };
// Discard the response headers, which are terminated by a blank line:
string header;
while (getline(s, header) && header != "\r")
;
}
int main()
{
try {
string server = "www.stroustrup.com";
boost::asio::ip::tcp::iostream s{ server, "http" }; // make a connection
connect_to_file(s, server, "C++.html"); // check and open file
regex pat{ R"((http://)?www([./#\+-]\w*)+)" }; // URL
for (auto x : get_strings(s, pat)) // look for URLs
cout << x << '\n';
}
catch (std::exception& e) {
std::cout << "Exception: " << e.what() << "\n";
return 1;
}
}
Давайте покажем Страуструпу, что такое небольшая и читаемая программа.
- Скачать
http://www.stroustrup.com/C++.html
Перечислите все ссылки:
http://www-h.eng.cam.ac.uk/help/tpl/languages/C++.html http://www.accu.org http://www.artima.co/cppsource http://www.boost.org ...
Вы можете использовать любой язык, но сторонние библиотеки не допускаются.
победитель
Ответ C ++ выиграл голосами, но он опирается на стороннюю библиотеку (которая запрещена правилами), и вместе с другим близким конкурентом Bash полагается на взломанный вместе HTTP-клиент (он не будет работать с HTTPS, gzip, перенаправляет и т. д.). Так что Вольфрам явный победитель. PowerShell (с улучшением по комментариям) приближается к другому решению, которое приближается к размеру и удобочитаемости , но ему не уделяется особого внимания. Основные языки ( Python , C # ) тоже подошли довольно близко.
Content-Type: text/html; charset=UTF-8
... Я отправлю ему письмо.boost/asio
используются там , который является библиотекой третьей стороны. Я имею в виду, как будут конкурировать языки, которые не включают выборку url / tcp как часть своей стандартной библиотеки?Ответы:
вольфрам
Это похоже на полный обман
Так что просто добавьте честный разбор сверху
источник
C ++
Основным недостатком является неуклюжий характер boost :: asio, я уверен, что он может быть еще короче с лучшей библиотекой.
источник
import urllib2
, C3 все еще может бытьusing System.Net
, Haskel все еще можетimport Network.HTTP
, но кодер C ++ должен оправдываться,#include <boost/asio.hpp>
как если бы он имел метрический набор специализированных, специально созданных библиотек C ++ (и C!) есть из чего выбрать то, за что стыдно, потому что комитет не стал насильно кормить вас конкретным ...System.Net
не обязателен, это просто высококачественная библиотека, соответствующая всем рекомендациям .NET, включенным в язык. Существуют альтернативные реализации, но наличие поддержки HTTP в стандартной библиотеке означает, что писать простые приложения просто, означает лучшую совместимость между сторонними библиотеками, означает меньше зависимостей, означает простую реализацию для фасадов и т. Д. Представьте себе мир безstd::string
, представьте, как все используют свою собственную библиотеку, представьте все трудности, которые с ней связаны.urllib2
является третьей стороной. Это в stdlib, как в C ++. в Python всегда доступен в отличие от C ++. Если бы нам было разрешено использовать сторонние модули; Я бы использовал или в Python.<iostream>
urllib2
<boost/asio.hpp>
lxml
BeautifulSoup
Pure Bash в Linux / OS X (без внешних утилит)
Программное обеспечение HTTP-клиента, как известно, раздутый. Мы не хотим такого рода зависимостей. Вместо этого мы можем протолкнуть соответствующие заголовки в поток TCP и прочитать результат. Не нужно вызывать архаичные утилиты, такие как grep или sed, чтобы проанализировать результат.
Мех - я полагаю, это может быть более читабельным ...
источник
mapfile
:)mapfile
идет с Bash 4.x. То же самое можно сделать и с помощьюwhile read
цикла.while read
вместоmapfile
. Думаю, более портативным и более читабельным.Python 2
Хромает, но работает
источник
l = re.findall('"((http)s?://.*?)"', u.urlopen(s).read())
urlopen()
). Что он должен делать с таким исключением, кроме краха и смерти? Если он все равно рухнет и умрет, то почему бы просто не позволить Python справиться с падением и смертью и вообще прекратить обработку исключений?urlopen
ошибки, а не (скажем) ловили их и вызывалиsys.exit("something's borked!")
. Если они делают последнее, я должен пойматьSystemExit
, что никогда не бывает весело.C #
источник
var html
, и, вероятно,var match
сбрить несколько символов.html
вообще избавляться от переменных, но это не то, что мне нужно.var
когда это не повлияет на семантику кода?«Нет третьей стороны» - заблуждение
Я думаю, что предположение «без третьей стороны» является ошибкой. И это специфическая ошибка, которая поражает разработчиков C ++, так как очень трудно сделать код многократного использования в C ++. Когда вы вообще что-то разрабатываете, даже если это небольшой скрипт, вы всегда будете использовать любые куски кода, которые можно использовать повторно.
Дело в том, что в таких языках, как Perl, Python, Ruby (если назвать несколько), повторное использование чужого кода не только легко, но и то, как большинство людей на самом деле пишут код большую часть времени.
C ++ с его почти невозможными в поддержании совместимыми ABI-требованиями делает эту работу гораздо сложнее, и в итоге вы получаете такой проект, как Boost, который представляет собой чудовищное хранилище кода и очень мало компоновается за его пределами.
Пример CPAN
Просто для удовольствия, вот пример, основанный на CPAN, с правильным синтаксическим анализом HTML, вместо того, чтобы пытаться использовать регулярное выражение для анализа HTML
источник
Оболочка UNIX
Также находит
ftp://
ссылку :)Другой способ, не полагаясь на
://
синтаксис:источник
lynx
это функционально эквивалентно сторонней библиотеке в этом сценарии.CSS 3
Этот код можно использовать в качестве пользовательского стиля для отображения только абсолютных ссылок на странице в неформатированном списке. Это может работать некорректно, если в вашем браузере установлен минимальный размер шрифта.
Он работает правильно с
http://www.stroustrup.com/C++.html
(обратите внимание!important
наbackground
). Чтобы работать на других страницах с большим количеством стилей, его необходимо расширить (сбросить больше свойств, пометить свойства как важные и т. Д.).Альтернативная версия, которая включает относительные ссылки, кроме внутристраничных ссылок, начинающихся с хэшей (к сожалению, она основана на жестко закодированной абсолютной ссылке):
источник
Clojure
источник
spit
,zipper
иlazy-cat
... :-)Emacs Lisp
источник
Scala
источник
ftp://ftp.research.att.com/pub/c++std/WP/CD2
?PHP 5
источник
'/"((http)s?://.*?)"/'
⇒'|"((http)s?://.*?)"|'
(в настоящее время ошибка); удалитьarray_unshift($m);
(в настоящее время вы, скорее всего, имели в виду ошибкуarray_shift
);print_r($m);
⇒print_r($m[1]);
(выводить только URL-адреса).PowerShell
Текстовый поиск по всем полным URL - адресам (включая JavaScript, CSS и т. Д.):
Или получить ссылки только в тегах привязки (включая относительные URL):
Укороченные версии из комментариев:
источник
iwr
это псевдоним дляInvoke-WebRequest
(PS3 +).(iwr "http://www.stroustrup.com/C++.html").Links.href
(или(iwr "http://www.stroustrup.com/C++.html").Links.href-match":"
только для абсолютных URI)D
источник
| sort | uniq
или вместо добавленияimport std.array
и изменить строку.filter!("a")){ writeln(_.front[1]); }
в этом:.filter!("a").map!(a => a.front[1]).array.sort.uniq){ writeln(_); }
. Заметьте, однако, что я только попробовал этот код и не доказал, что он правильный или «идиоматический». :)Node.js
источник
require('http').get
работает ли ? Если это так, то мы можем отказаться от оператора var и сократить другую строку.Рубин
источник
%r{"(https?://[^"]+)"}
. Также вы можете использовать,Net::HTTP.get('www.stroustrup.com', '/C++.html')
чтобы сократить запрос (и сохранить его читабельным). Поэтому весь код может быть в одной строке (удерживая ее чтения):puts Net::HTTP.get("www.stroustrup.com", "/C++.html").scan(%r{"(https?://[^"]+)"})
. Запустите его,ruby -rnet/http
и вам даже не нужнаrequire 'net/http'
линия.Haskell
Некоторые проблемы
"\w"
в Text.Regex.Posixисточник
result
указан явно? Это должно быть полностью ограничено его использованием вunlines
.Network.HTTP
ни того, ни другого . (Хотя они находятся на платформе Haskell и, конечно, на Hackage, так что ...)TextRegex.Posix
base
network
не вbase
том, так что, за исключением того, чтобы свернуть ваши собственные привязки сокетов, нет никакого практического способа сделать это простоbase
.PHP
Насколько я могу судить, большинство современных установок PHP поставляются с обработкой DOM, поэтому вот тот, который фактически проходит через якоря внутри HTML:
Внутренний цикл может быть сокращен до:
источник
1
вместоtrue
дляin_array
строгого поиска. Вы также можете опустить скобки. Я не совсем уверен, но, возможно, вы могли бы броситьhttp
и оставить только://
(идти без схемы). ,if ( ) {}
в пользуin_array() and print $url.PHP_EOL
. Но да, вы получите еще один +1 (если бы мог) для лучшей читабельности :)@\DOMDocument
. Только что попробовал и могу подтвердить, что это работает.::loadHTMLFile()
статически, а добавлять@
только шкуры, которые являются артефактом.Unix Shell
Хотя я должен признать, что это не сработает, если в строке более одной ссылки.
источник
curl http://www.stroustrup.com/C++.html
сохраняет несколько символов.wget
GNU (как и bash), вы можете утверждать, что он не является сторонним. Но,curl
безусловно, является сторонним.ftp://ftp.research.att.com/pub/c++std/WP/CD2
иhttps://www.youtube.com/watch?v=jDqQudbtuqo&feature=youtu.be
?Ява
источник
Scanner
вы можете сделать так, чтобы он обрабатывал шаблон регулярных выражений непосредственно для ссылок и просматривалScanner
результаты.Groovy
источник
SQL (SQL Anywhere 16)
Определите хранимую процедуру для извлечения веб-страницы
Создайте набор результатов, используя один запрос
Ограничения: это дает до 256 ссылок. Если существует больше ссылок, увеличьте 256 до соответствующего значения.
источник
CoffeeScript / NodeJS
источник
Perl
источник
use v5.10;
иsay for $response->content
...say
весьма полезны, и, на мой взгляд, более понятны здесь. (Кроме того, за последние 13 лет было довольно много совершенно не связанных с perl6ism улучшений в perl5; возможно, стоит попробовать.)say
в этом случае, вероятно, более читабельным, особенно для тех, кто менее знаком с Perl.р
... хотя R написан в основном на C ... так что, вероятно, несколько строк кода C за этими двумя строками кода R.
источник
Objective-C
источник
Tcl
источник
[
. Но это выбор стиля.Идти
PS этот код считывает весь источник в память, поэтому рассмотрите возможность использования
regexp.FindReaderIndex
поиска в потоке, что сделает приложение пуленепробиваемым.источник
CJam
CJam не имеет регулярных выражений, поэтому мне пришлось использовать другой подход в этом:
Сначала я конвертирую все
'
в"
, затем делю на все"
, беру каждую альтернативную строку, а затем, наконец, фильтрую этот список для строк, начинающихся сhttp://
илиhttps://
. После этого просто напечатайте каждую отфильтрованную строку в новой строке.Попробуйте использовать интерпретатор Java, например
где file.cjam содержит содержимое кода выше.
источник
''/'"f/:+
для''/'"*'"/'"f/0f=
.'"f/0f=
там? Это должно что-то делать (2%
например)?F #
Этот код может быть намного короче, но я бы написал что-то вроде этого, если бы когда-нибудь ожидал, что мне придется читать или использовать этот код снова, так что в нем много ненужных аннотаций типов. Он демонстрирует использование активного шаблона MatchValue для включения сопоставления с шаблоном со стандартным типом соответствия CLR.
Edit я сделал getLinks свою собственную функцию
источник