>> wybierz styl >> es :: ns :: bs

Weblog Tomasza Przechlewskiego [Zdjęcie T. Przechlewskiego] [[Ikona]]


scrum
random image [Photo gallery]
Zestawienie tagów
1-wire | 18b20 | 1wire | 2140 | 3rz | alsamixer | amazon | anniversary | antypis | apache | api | arm | astronomy | asus | atom.xml | awk | aws | balcerowicz | balta | bash | berlin | bibtex | bieszczady | biznes | blogger | blogging | blosxom | borne-sulinowo | breugel | bt747 | canon | cedewu | chello | chown | chujowetaśmy | cmentarz | contour | cron | css | csv | curl | d54250wykh | debian | dejavu | dhcp | dht22 | dia | docbook | dom | ds18b20 | dyndns | dynia | ebay | economy | ekonomia | elka | elm | emacs | emacs23 | english | ess | eu | excel | exif | exiftool | f11 | fc | fc11 | fc15 | fc5 | fc8 | fedora | fedora21 | fenix | ffmpeg | finepix | firefox | flickr | fontforge | fontspec | fonty | fop | foto | france | francja | fripp | fuczki | fuji | fuse | gammu | garmin | gawk | gazwyb | gdańsk | gdynia | geo | georgia | gft | git | github | gmail | gnokii | gnus | google | googlecl | googleearth | googlemaps | gphoto | gphoto2 | gps | gpsbabel | gpsphoto | gpx | gpx-viewer | greasemonkey | gruzja | grzyby | haldaemon | handbrake | historia | history | hitler | holocaust | holokaust | hpmini | humour | iblue747 | ical | iiyama | ikea | imap | inkscape | inne | internet | j10i2 | javascript | jhead | k800i | kajak | kamera | kleinertest | kml | kmobiletools | knuth | kod | kolibki | komorowski | konwersja | krutynia | kuchnia | kurski | latex | latex2rtf | latex3 | lcd | legend | lenny | lesund | lewactwo | liberation | linux | lisp | lisrel | litwa | logika | ltr | lwp | m2wś | mapsource | marvell | math | mathjax | mazury | mbank | mediolan | mencoder | mh17 | michalak | microsoft | monitor | mp4box | mplayer | ms | msc | msw | mtkbabel | museum | muzyka | mymaps | mysql | nanopi | natbib | navin | neo | neopi | netbook | niemcy | niemieckie zbrodnie | nikon | nowazelandia | nuc | nxml | oauth | oauth2 | obituary | okular | olympus | ooffice | ooxml | opera | otf | otftotfm | other | overclocking | panoramio | pdf | pdfpages | pdftex | pdftk | perl | photo | photography | picasa | picasaweb | pim | pine | pit | plotly | pls | plugin | po | politics | polityka | polsat | postęp | powerpoint | prelink | problem | propaganda | pstoedit | putin | python | r | radio | random | raspberry pi | refugees | relaxng | ridley | router | rower | rowery | rpi | rsync | rtf | ruby | rugby | russia | rwc | rwc2007 | rwc2011 | rzym | samba | sem | sheevaplug | sienkiewicz | signature | sks | skype | skytraq | smoleńsk | sqlite | srtm | ssl | statistics | stats | statystyka | stix | suwałki | svg | svn | swornegacie | szwajcaria | terrorism | tex | texgyre | texlive | thunderbird | tomato | tourism | tramp | trang | truetype | ttf | turystyka | tusk | tv | tv5monde | twitter | typetools | ubuntu | uchodźcy | udev | umap | unix | upc | updmap | ups | utf8 | varia | video | vienna | virb edit | vostro | wammu | wdc | wdfs | webcam | webdav | wh2080 | wiedeń | wikicommons | wilno | windows | windows8 | wine | wioślarstwo | word | wordpress | wrt54gl | ws1080 | wtyczka | ww2 | www | wybory | wybory2015 | włochy | xemex | xetex | xft | xhtml | xine | xml | xmllint | xsd | xslt | xvidtune | youtube | yum | zakopane | zakupy | zdf | łeba | świdnica
Pobrania via google: [[Ikona]]
Archiwum
Inne blogi
N. Walsh | Morten H. Frederiksen | B. Clementson | prawo.vagla.pl | F. Hecker | M. Olson | J. Tennison | J. Clark | M. Nottingham | M. Shuttleworth | T. Isakowicz-Zalewski | J. Anglim | José A. Ortega Ruiz Modern Perl
Inne tematyczne
Ashwin Amanna | wiesia.nets.pl | Wojt | rwm.org.pl | DataBlog | Revolutions | Learning R | A. Gelman | C. Nel | J. Vogelgesang | ubl.xml.org/ | J.D. Long |
O stronie
wykorzystywany jest blosxom plus następujące wtyczki: tagging, flatarchives, rss10, lastbuilddatexhtmlmime. Niektóre musiałem dopasować nieco do swoich potrzeb. Więcej o blosxom jest tutaj
Subskrypcja
RSS 1.0
Kursy walut

Już kiedyś kombinowałem z kursami walut używając do tego plugina Firefoxa. Teraz potrzebowałem czegoś co możnaby uruchmić jako skrypt, korzystający przy tym z jakiegoś wiarygodnego źródła danych i to najlepiej poprzez XML/API a nie html scraping (cf. np. Screen scraping with Perl), bo to ostatnie może nagle przestać działać jak się layout strony zmieni. Krótkie rozpoznanie w ww. kierunku dało w rezultacie następujące potencjalne rozwiązania:

1. Skrypt Johna Bokmy działający w oparciu o dane ze strony www.xe.com (wykorzystuje html scraping). Xe.com wygląda -- sądząc po zawartości serwisu WWW -- na renomowaną firmę ale skrypt nie działa, a nawet gdyby działał to Xe.com zabrania korzystania z ich strony w ten sposób (o czym zresztą John Bokma też pisze).

2. Pakiet Perla pn. Finance-Currency-Convert-WebserviceX, korzystający z kolei z danych ze strony webservicex.net. Nie znam firmy Generic Objects Technologies Ltd, która animuje serwis webservicex.net. Ponieważ wydało mi się, że firma nie jest specjalnie wiarygodna -- zapewne niesłusznie -- nie instalowałem ww. biblioteki Perla i szukałem dalej.

3. Pakiet Finance::Currency::Convert::Yahoo. Korzysta z danych Yahoo Finance i wykorzystuje html scraping. Ponieważ do Yahoo mam większe zaufanie, postanowiłem toto wypróbować:

perl -MCPAN -e 'install Finance::Currency::Convert::Yahoo'
perl -e 'use Finance::Currency::Convert::Yahoo; \
  print Finance::Currency::Convert::Yahoo::convert(1,'USD','PLN');'

Wygląda, że działa i to mimo tego, że ostatnia wersja pakietu jest z roku 2005.

4. Dane z NBP udostępnione na stronie www.nbp.pl/Kursy/Kursya.html. Na dole tej strony jest link do pliku XML. Problem przy zautomatyzowaniu pobierania pliku jest z jego nieprzewidywalnie dziwną nazwą, np. a140z080718.xml. Powyższe oznacza, że to tabela o numerze 140 z dnia 2008/07/18. Oczywiście data to pryszcz (bieżąca) gorzej z numerem tabeli, który wydaje się być trudny do wyznaczenia.

Reasumując: niby prosta i potrzebna sprawa ale podejrzanie brak jest serwisu, który by oferowałby konwersję walut via API (wyjątek: webservicex.net, ale imho podejrzany:-). Pozostaje html scraping albo NBP. Google coś tajemniczo nic ,,w tym temacie'' nie ma -- może nieudolnie szukałem.

Dopisane 20 lipca 2008: czytelnik bloga Krzysztof R. (nazwisko do wiadomości Redakcji:-) już wczoraj zwrócił słusznie uwagę, że Przykładowe zapytanie: http://www.google.com/search?q=1 pln in usd&hl=en zwróci następujący ciąg znaków w treści strony: 1 Polish zloty = 0.495565 U.S. dollars. Ciąg ten można łatwo wydobyć przy pomocy wyrażenia regularnego.
Dziękuję za powyższą wskazówkę...

url | Sat, 19/07/2008 16:23 | tagi: , ,
Ebay REST API

`Na szybko' zrobiłem trzy skrypty wykorzystujące Ebay REST API. Skrypty mają ułatwić wyszukiwanie oraz archiwizowanie interesujących mnie aukcji. Próbowałem wykorzystać do ww. celu gotowe narzędzie ale jakoś nic interesującego nie znalazłem. Bibioteka Net::eBay jakaś taka słabo udokumentowana i nieporęczna mi się wydała podobnie jak WWW::Search::Ebay. (Por. skrypt opisany np. tutaj.)

Najbardziej skomplikowany z moich skryptów wykorzystuje metodę FindItemsAdvanced do wyszukania aukcji. Metoda FindItemsAdvanced ma parametr MaxEntries określający liczbę zwracanych aukcji. Parametr ten ma domyślną wartość 20 a maksymalną akceptowaną wartością jest 200 (jeżeli podamy 0 to metoda zwróci liczbę pasujących do zapytania aukcji). Jeżeli aukcji jest więcej niż wynosi wartość MaxEntries, to aby ściągnąć kolejne aukcje metodę FindItemsAdvanced trzeba wykonać wielokrotnie, podając odpowiednią wartość parametru PageNumber. Przykładowo jeżeli aukcji jest 121, a wartość MaxEntries wynosi 40, to trzeba FindItemsAdvanced wykonać 4 razy.

Parametr ItemSort ustala porządek sortowania. Wartość StartDate tego parametru powoduje, że aukcje są posortowane według daty wstawienia na ebay (daty/czasy są definiowane w GMT oczywiście).

W związku z takim działaniem metody FindItemsAdvanced skrypt ebay_rest_search.pl najpierw ustala liczbę pasujących aukcji, a następnie pobiera kolejno strony w pętli do momentu aż znajdzie aukcję już pobraną (aukcje są przechowywane w haszu %IdxLog, który jest przechowywany na dysku przy wykorzystaniu funkcji store/retrieve modułu Storable). Nowe aukcje są dodawane do hasza %IdxLog:

## Uproszczony fragment skryptu:
while ( ($current_page >= 0) && ($current_page <= $last_page ) ) {
  $current_page++;
  $xml = make_call('search_text' => $search_text, 'per_page' => $MAX_PER_PAGE,
     'site_id' => "$this_site_id", 'page' => $current_page);

  my $xm = $xmlp->XMLin($xml,  ForceArray => 0);
  my $list = $xm ->{'SearchResult'}->{ItemArray}->{Item} ;

  foreach $item ( @{$list} ) { 
    $item_id = $item->{'ItemID'};

    if ( exists $IdxLog{ $item_id } ) {## zakończ 
      $current_page = -99; last ;  }
    else { $new_items++;
      $IdxLog{ $item_id } = [ $item->{'Title'}, $item->{'StartTime'}, $item->{'EndTime'},
          $item->{'GalleryURL'}, $item->{'ListingStatus'}, 
	  $item->{'ViewItemURLForNaturalSearch'}, $day_added ];
    }
  }
}

Metoda XMLin jest z modułu XML::Simple. Moduł ten definiuje prosty interfejs do dokumentów XML. Po wykonaniu XMLin, zawartość dokumentu jest dostępna w postaci elementów zagnieżdżonych list/haszy. Można oczywiście analizować dokument XML w inny sposób, nie upieram się że XML::Simple jest najlepszym pomysłem.

Uwaga: metoda FindItemsAdvanced nie umożliwia przeszukania całej bazy eBay (odpowiednik wyszukiwanie zaawansowane->preferowana lokalizacja->cały świat). Parametr siteid określa, który serwis eBay ma być przeszukany. Jeżeli podamy id=0 to zapytanie dotyczyć będzie ebay.com, a jeżeli id=212, to ebay.com.pl, itd. Aby przeszukać cały ebay to trzeba wykonać FindItemsAdvanced wielokrotnie.

Następnie hasz %IdxLog jest przeglądany w pętli celem archiwizacji aukcji, które się zakończyły:

for $id (sort { $IdxLog{$a}[2] cmp $IdxLog{$b}[2] } keys %IdxLog) {
   $end_time = $IdxLog{$id}[2]; # drugi element listy to czas zakończenia
   $time_to_end = $now_in_seconds - ebaydate2seconds( $end_time );

   if ($time_to_end > 0 && $status =~ /Active/) {# Aukcja zakończona
      $result = `ebay_rest_item.pl -i $id`; ## ściągnij innym skryptem

      if ($? > 0 ) { warn "Problems backuping $id\n"; } else {
	$IdxLog{$id}[4] = 'Completed'; # zmień status na zakończoną
	$completed_items++; }
   }
}

Zmienna $now_in_seconds, to liczba sekund od epoch a funkcja ebaydate2seconds zmienia napis zawierający czas w formacie zwracanym w dokumencie XML na liczbę sekund od epoch. Jeżeli różnica czasu bieżącego a czasu zakończenia aukcji wskazuje, ze aukcja się zakończyła jest ona ściągana za pomocą skryptu ebay_rest_item:

#!/usr/bin/perl
use LWP::Simple;
use Getopt::Long;

my $verbose = 1;
use lib "$ENV{HOME}/.ebay"; ## configuration files

GetOptions('item=s' => \$ebay_item_id, 'help' => \$print_help, );
unless ($ebay_item_id) { die "Usage: $0 -i <item_id>\n"; }

our $netebay_rc;
require("netebay.rc");

my $url = "http://open.api.ebay.com/shopping?callname=GetSingleItem" .
  "&responseencoding=XML" .
  "&appid=$EBayRC{p_appid}" .
  "&siteid=0" .
  "&version=525" .
  "&ItemID=$ebay_item_id" .
  "&IncludeSelector=Description,Details";

my $xml = get $url ;

## In a scalar context m//g iterates through the string, returning true each time
## it matches. If you modify the string in any way, the match position is reset.
my %Pics;
while ($xml =~ /<PictureURL>([^<>]+)<\/PictureURL>/mg) { $Pics{$1} = 1; }

my $pic, $ori_pic;

for $pic  (keys %Pics ) { 
  $ori_pic = $pic; $ori_pic =~ s/\?/\\\?/g; # zmieniamy meta znaki: ?
  $pic =~ s/\?[^\?]+$//g;
  my ($content_type, $document_length, $modified_time, $expires, $server) = head($pic);

  $pic_no++;

  if ( $content_type =~ /image/ ) {  $content_type =~ m/\/(.+)$/;
    $local_file = "${ebay_item_id}_${pic_no}.$1"; } 
  else { $local_file = "${ebay_item_id}_${pic_no}.JPG?"; } ## problems with content_type

  warn "Storing $pic in  $ARCH_DIR/$local_file ... \n";
  getstore($pic, "$ARCH_DIR/$local_file");

  ## zapisz lokalną nazwę jako atrybut
  ## Uwaga na metaznaki (? już jest obezwładniony):
  $xml =~ s/<PictureURL>$ori_pic/<PictureURL local='$local_file'>$ori_pic/;

}

open (LOG, ">$ARCH_DIR/$ebay_item_id.xml" ) || 
     die " ** cannot open $ARCH_DIR/$ebay_item_id.xml **";

print LOG "$xml\n";

Ten skrypt zapisuje po prostu dokument XML zwrócony przez metodę GetSingleItem. Argumentem skryptu jest id aukcji. Jedyne utrudnienie związane jest z pobraniem zdjęć. Adresy URL do zdjęć są zdefiniowane wewnątrz elementów PictureURL. Aby uprościć skrypt elementy te są wyszukiwane przy pomocy prostego wyrażenia regularnego. Konstrukcja:

while ($napis =~ /wzorzec/mg) { ## $1 zawiera dopasowany do wzorca napis  }

Będzie dopasowywać wzorzec do $napisu iteracyjnie. W każdej iteracji zmienna $1 będzie zawierała kolejny napis pasujący do wzorca. Aby powyższe działało prawidłowo $napis nie może być modyfikowany wewnątrz pętli (i nie jest). Adresy URL są składowane w haszu %Pics.

Teraz hasz %Pics jest przeglądany w pętli. Zdjęcia są ściągane a dodatkowo dokument XML jest modyfikowany -- też za pomocą wyrażeń regularnych -- w taki sposób, że do elementu dodawana jest informacja o nazwie lokalnej zdjęcia. Nazwa lokalna jest tworzona automatycznie jako: ${ebay_item_id}_${pic_no}.$1, gdzie ${pic_no} jest kolejnym numerem zdjęcia dla aukcji o numerze ${ebay_item_id}.

Ostatni skrypt jest najprostszy i drukuje fragment drzewa kategorii eBay (konkretnie podkategorie dla kategorii, której id podano jako argument skryptu). Korzeń drzewa ma id równe -1.

#!/usr/bin/perl
use LWP::Simple;
use Getopt::Long;

use lib "$ENV{HOME}/.ebay"; ## configuration files
use $ebay_site_id = 'US'; ## 0 is US ebay

GetOptions( 'site=s' => \$ebay_site_id, 'category=i' => \$ebay_cat_id,
    'help' => \$print_help, );
unless ($ebay_cat_id) {$ebay_cat_id = -1 } ## top-level

our $netebay_rc;
require("netebay.rc");

my $site_id_code = $Sites_Ids{$ebay_site_id};

my $url  = "http://open.api.ebay.com/Shopping?callname=GetCategoryInfo" .
   "&appid=$EBayRC{p_appid}" .
   "&version=533" .
   "&siteid=$site_id_code" .
   "&CategoryID=$ebay_cat_id" .
   "&IncludeSelector=ChildCategories";

print (get $url) . "\n" ;

Ten skrypt przyda się do udoskonalenia działania ebay_rest_search, tak żeby przeszukiwania dotyczyły tylko wybranych kategorii. Niestety eBay nie ma jednolitej hierarchii kategorii. Ten sam przedmiot może być różnie klasyfikowany.

No i tyle. Pozostaje umieścić ebay_rest_search w crontabie. Skrypty są tutaj.

url | Sun, 22/06/2008 16:12 | tagi: , , , ,
Microsoft kupuje Yahoo

Podobno MS chce kupić za 44 Mld USD (z ogonkiem) Yahoo. Nie będę się mądrzył czy to dobrze czy źle ale tak dla ilustracji czego boi się Balmer, poniżej tabelka rocznych zysków netto zainteresowanych firm (wiersz oznaczony jako % oznacza dynamikę zysku rok/rok_poprzedni * 100 - 100; ostatni wiersz to udział zysku Google w zysku MSFT, w %).

Symbol      2007       2006      2005      2004      2003       2002
--------------------------------------------------------------------
MSFT   14,065.00  12,599.00  12,254.00  8,168.00  7,531.00  5,355.00 
 %         11.63       2.80      50.02      8.46     40.63        --

YHOO      660.00     751.39   1,896.23    839.55    237.88     42.81
 %         -12.3     -61.00     125.83    252.93    455.66        --

GOOG        --+    3,077.44   1,465.40    399.12    105.65     99.66
 %          --+      101.00     267.15    277.77      6.01        --

GOOG/MSFT   --        24.42      11.96      4.88      1.40      1.86
--------------------------------------------------------------------
+ Brak danych za rok 2007.

Źródło: MSFTGOOGYHOO.

Jak widać zyski Google mają dramatyczną z punktu widzenia firmy Microsoft, w tym, a zwłaszcza jej akcjonariuszy, dynamikę. Jak tak dalej by poszło, Balmer jest już dead and buried ze swoim szmelcem aka pomnikiem dla ludzkości od Bila G. Z drugiej strony Yahoo też tak miało w latach 2005--2003 ale od dwóch lat jest kiepsko. Na zdrowy chłopski nie da się w nieskończoność robić super biznesu sprzedając Windows+Office. Ale czy da się długo robić super biznes sprzedając reklamy? Też nie wiadomo. MS w Internecie nic nie znaczy, więc kupno Yahoo niby nie jest złym pomysłem, ale... Ale Yahoo za wyjątkiem flickr.com z niczym (w przeciwieństwie do Google) mi się nie kojarzy... Jednym słowem zobaczymy...

Ważniejszy w całej tej sprawie jest ewentualny zakup przez Microsoft firmy od lat związanej/sponsorującej wiele projektów OS, por. what-happens-if-microsoft-buys-yahoo albo Yahoo! buy would give Microsoft ownership of open source e-mail, projects, code. Ugh.

url | Sat, 02/02/2008 21:27 | tagi: , , ,