Web scraping
You are encouraged to solve this task according to the task description, using any language you may know.
Create a program that downloads the time from this URL: http://tycho.usno.navy.mil/cgi-bin/timer.pl and then prints the current UTC time by extracting just the UTC time from the web page's HTML.
If possible, only use libraries that come at no extra monetary cost with the programming language and that are widely available and popular such as CPAN for Perl or Boost for C++.
AutoHotkey
<lang AutoHotkey> UrlDownloadToFile, http://tycho.usno.navy.mil/cgi-bin/timer.pl, time.html FileRead, timefile, time.html pos := InStr(timefile, "UTC") msgbox % time := SubStr(timefile, pos - 9, 8) </lang>
AWK
This is inspired by GETURL example in the manual for gawk.
#! /usr/bin/awk -f BEGIN { purl = "/inet/tcp/0/tycho.usno.navy.mil/80" ORS = RS = "\r\n\r\n" print "GET /cgi-bin/timer.pl HTTP/1.0" |& purl purl |& getline header while ( (purl |& getline ) > 0 ) { split($0, a, "\n") for(i=1; i <= length(a); i++) { if ( a[i] ~ /UTC/ ) { sub(/^<BR>/, "", a[i]) printf "%s\n", a[i] } } } close(purl) }
C
There's no any proper error handling.
<lang c>#include <stdio.h>
- include <string.h>
- include <curl/curl.h>
- include <sys/types.h>
- include <regex.h>
- define BUFSIZE 16384
size_t lr = 0;
size_t filterit(void *ptr, size_t size, size_t nmemb, void *stream) {
if ( (lr + size*nmemb) > BUFSIZE ) return BUFSIZE; memcpy(stream+lr, ptr, size*nmemb); lr += size*nmemb; return size*nmemb;
}
int main() {
CURL *curlHandle; char buffer[BUFSIZE]; regmatch_t amatch; regex_t cregex;
curlHandle = curl_easy_init(); curl_easy_setopt(curlHandle, CURLOPT_URL, "http://tycho.usno.navy.mil/cgi-bin/timer.pl"); curl_easy_setopt(curlHandle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, filterit); curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, buffer); int success = curl_easy_perform(curlHandle); curl_easy_cleanup(curlHandle);
buffer[lr] = 0; regcomp(&cregex, "UTC$", REG_NEWLINE); regexec(&cregex, buffer, 1, &amatch, 0); int bi = amatch.rm_so; while ( bi-- > 0 ) if ( memcmp(&buffer[bi], "
", 4) == 0 ) break;
buffer[amatch.rm_eo] = 0;
printf("%s\n", &buffer[bi+4]);
regfree(&cregex); return 0;
}</lang>
Common Lisp
<lang lisp>BOA> (let* ((url "http://tycho.usno.navy.mil/cgi-bin/timer.pl")
(regexp (load-time-value (cl-ppcre:create-scanner "(?m)^.{4}(.+? UTC)"))) (data (drakma:http-request url))) (multiple-value-bind (start end start-regs end-regs) (cl-ppcre:scan regexp data) (declare (ignore end)) (when start (subseq data (aref start-regs 0) (aref end-regs 0)))))
"Aug. 12, 04:29:51 UTC"</lang>
E
<lang e>interp.waitAtTop(when (def html := <http://tycho.usno.navy.mil/cgi-bin/timer.pl>.getText()) -> {
def rx`(?s).*>(@time.*? UTC).*` := html println(time)
})</lang>
Erlang
Using regular expressions:
<lang erlang>-module(scraping).
-export([main/0]).
-define(Url, "http://tycho.usno.navy.mil/cgi-bin/timer.pl").
-define(Match, "
(.+ UTC)").
main() -> inets:start(), {ok, {_Status, _Header, HTML}} = http:request(?Url), {match, [Time]} = re:run(HTML, ?Match, [{capture, all_but_first, binary}]), io:format("~s~n",[Time]). </lang>
Forth
<lang forth> include unix/socket.fs
- extract-time ( addr len type len -- time len )
dup >r search 0= abort" that time not present!" dup >r begin -1 /string over 1- c@ [char] > = until \ seek back to
at start of line r> - r> + ;
s" tycho.usno.navy.mil" 80 open-socket dup s\" GET /cgi-bin/timer.pl HTTP/1.0\n\n" rot write-socket dup pad 4096 read-socket s\" \r\n\r\n" search 0= abort" can't find headers!" \ skip headers s" UTC" extract-time type cr close-socket </lang>
Java
<lang java>import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection;
public class WebTime{
public static void main(String[] args){
try{
URL address = new URL(
"http://tycho.usno.navy.mil/cgi-bin/timer.pl");
URLConnection conn = address.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while(!(line = in.readLine()).contains("UTC"));
System.out.println(line.substring(4));
}catch(IOException e){
System.err.println("error connecting to server.");
e.printStackTrace();
}
}
}
</lang>
OCaml
<lang ocaml>let () =
let _,_, page_content = make_request ~url:Sys.argv.(1) ~kind:GET () in
let lines = Str.split (Str.regexp "\n") page_content in let str = List.find (fun line -> try ignore(Str.search_forward (Str.regexp "UTC") line 0); true with Not_found -> false) lines in let str = Str.global_replace (Str.regexp "
") "" str in print_endline str;
- </lang>
There are libraries for this, but it's rather interesting to see how to use a socket to achieve this, so see the implementation of the above function make_request on this page.
Perl
<lang perl>use LWP::Simple;
my $url = 'http://tycho.usno.navy.mil/cgi-bin/timer.pl';
get($url) =~ /
(.+? UTC)/
and print "$1\n";</lang>
Python
<lang python>import urllib
page = urllib.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl') for line in page:
if ' UTC\n' in line: print line.strip()[4:] break
page.close()</lang> Sample output:
Aug. 20, 19:50:38 UTC
R
First, retrieve the web page. See HTTP_Request for more options with this. <lang R> library(RCurl) webpage <- getURL("http://tycho.usno.navy.mil/cgi-bin/timer.pl") </lang> Now parse the html code into a tree and retrieve the interesting bit <lang R> library(XML) pagetree <- htmlTreeParse(webpage ) timesnode <- pagetree$children$html$children$body$children$h3$children$pre$children timesnode <- timesnode[names(timesnode)=="text"] </lang> Finally, find the line with universal time and parse it <lang R> timestrings <- sapply(timesnode, function(x) x$value) index <- grep("Universal Time", timestrings) utctimestr <- strsplit(timestrings[index], "\t")$text[1] utctime <- strptime(utctimestr, "%b. %d, %H:%M:%S UTC")
- Print the date in any format you desire.
strftime(utctime, "%A, %d %B %Y, %H:%M:%S") </lang>
Monday, 03 August 2009, 16:15:37
Ruby
<lang ruby>require "open-uri"
open('http://tycho.usno.navy.mil/cgi-bin/timer.pl') do |p|
p.each_line do |line| if line =~ /UTC\n/ puts line[4..-1] break end end
end</lang>
Tcl
<lang tcl>package require http
set request [http::geturl "http://tycho.usno.navy.mil/cgi-bin/timer.pl"]
if {[regexp -line {
(.* UTC)} [http::data $request] --> utc]} {
puts $utc
}</lang>
UNIX Shell
This solution uses curl, which can be downloaded for free (and very easily on GNU/Linux systems), and popular (at list in the GNU and *n*x world) utilities programs like grep and sed.
#! /bin/bash curl -s http://tycho.usno.navy.mil/cgi-bin/timer.pl | grep 'UTC$' | sed -e 's/^<BR>//'
Ursala
This works by launching the wget command in a separate process and capturing its output. The program is compiled to an executable command. <lang Ursala>#import std
- import cli
- executable ('parameterized',)
whatime =
<.file$[contents: --<>]>+ -+
@hm skip/*4+ ~=(9%cOi&)-~l*+ *~ ~&K3/'UTC', (ask bash)/0+ -[wget -O - http://tycho.usno.navy.mil/cgi-bin/timer.pl]-!+-</lang>
Here is a bash session.
$ whatime Jun. 26, 20:49:52 UTC