概要

  • XML::Simple を使って XML を読む
  • Amazon Web Services の BrowseNodeSearch の結果をXML::Simpleを使って解析し、子ノードを探索する。
  • 親ノード/子ノードの表示だけ行いファイル保存はしないようにした。(2009/12/05)
  • AssociateTagを指定するようにした。(2011/10/27)
  • Web版

BrowseNodeSearch

  • 下記URLにリクエストすることで、あるBrowseNodeの子ノード一覧を取得できる。
    • XXXXは調べたいBrowseNode。
      http://webservices.amazon.co.jp/onca/xml
        ?Service=AWSECommerceService
        &Operation=BrowseNodeLookup
        &ResponseGroup=BrowseNodeInfo
        &AssociateTag=xxxx-22
        &BrowseNodeId=XXXX

スクリプト

  • BrowseNodes2.zip
    #!/usr/local/bin/perl
    #
    # BrowseNodes2.pl
    # Amazon Web Services BrowseNodes 探索スクリプト
    # by TakeAsh
    #
    # http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html
    #
    # 2009.12.05	v2.00	親ノード/子ノードの表示だけ行いファイル保存はしないようにした。
    # 2011.10.27	v2.01	AssociateTagを指定するようにした。
    
    use strict;
    use warnings;
    use utf8;
    use Encode;
    use URI::Amazon::APA;
    use LWP::UserAgent;
    use XML::Simple;
    use YAML::Syck;
    
    $YAML::Syck::ImplicitUnicode = 1;
    
    my $charsetConsole	= 'CP932';
    #my $charsetInFile	= 'UTF-8';
    #my $charsetOutFile	= 'UTF-8';
    
    binmode( STDIN,  ":encoding($charsetConsole)" );
    binmode( STDOUT, ":encoding($charsetConsole)" );
    binmode( STDERR, ":encoding($charsetConsole)" );
    
    my $confyaml = './ID.yaml';
    my $conf = YAML::Syck::LoadFile( $confyaml ) 
    	or die( "$confyaml: $!\n" );
    
    my $nodelistbaseyaml = './BrowseNodeIDs-JP.yaml';
    my $nodelistbase = YAML::Syck::LoadFile( $nodelistbaseyaml ) 
    	or die( "$nodelistbaseyaml: $!\n" );
    
    unless ( @ARGV ){
    	print "BrowseNodeId\tCategory\n";
    	foreach my $nodeid ( sort by_number ( keys( %{$nodelistbase} ) ) ){
    		print "$nodeid\t$nodelistbase->{$nodeid}\n";
    	}
    	die( "usage: $0 <browse_node_id> [ <browse_node_id> ...]\n" );
    }
    my $browsenodeid = join( ",", @ARGV ) || '465610';
    
    my $u = URI::Amazon::APA->new( 'http://ecs.amazonaws.jp/onca/xml' );
    $u->query_form(
    	Service			=> 'AWSECommerceService',
    	Operation		=> 'BrowseNodeLookup',
    	ResponseGroup	=> 'BrowseNodeInfo',
    	AssociateTag	=> $conf->{'ASSOCIATE_TAG'},
    	BrowseNodeId	=> $browsenodeid,
    );
    $u->sign(
    	key    => $conf->{'AWS_ACCESS_KEY_ID'},
    	secret => $conf->{'SECRET_ACCESS_KEY'},
    );
    
    my $ua = LWP::UserAgent->new;
    my $r  = $ua->get($u);
    if ( $r->is_success ){
    	my $content = XMLin( 
    		$r->content, 
    		ForceArray	=> [ 'BrowseNode', 'Error' ], 
    		KeyAttr		=> { 'BrowseNode' => '+BrowseNodeId' } 
    	);
    #	die( YAML::Syck::Dump( $content ) );
    	if ( my $errors = $content->{'BrowseNodes'}->{'Request'}->{'Errors'} ){
    		die( YAML::Syck::Dump( $errors ) );
    	}
    	my $nodelist = $content->{'BrowseNodes'}->{'BrowseNode'};
    #	die( YAML::Syck::Dump( $nodelist ) );
    	foreach my $nodeid ( sort by_number ( keys( %{$nodelist} ) ) ){
    		my $node = $nodelist->{$nodeid};
    		print "Node\t\t$node->{'BrowseNodeId'}\t$node->{'Name'}\n";
    		printAncestors( $node );
    		my $children = $node->{'Children'}->{'BrowseNode'};
    		foreach my $childid ( sort by_number ( keys( %{$children} ) ) ){
    			my $child = $children->{$childid};
    			print "Child\t\t$child->{'BrowseNodeId'}\t$child->{'Name'}\n";
    		}
    	}
    } else {
    	die( $r->status_line, "\n" );
    }
    
    exit;
    
    sub by_number
    {
      $a <=> $b;
    }
    
    sub printAncestors
    {
    	my( $browsenode ) = @_;
    	if ( my $ancestors = $browsenode->{'Ancestors'}->{'BrowseNode'} ){
    		foreach my $nodeid ( keys( %{$ancestors} ) ){
    			my $node = $ancestors->{$nodeid};
    			print "Ancestor\t$node->{'BrowseNodeId'}\t$node->{'Name'}\n";
    			printAncestors( $node );
    		}
    	}
    }
    
    # EOF

エラーメッセージ対応

https 対応

  • URI::Amazon::APA 0.05 は https に対応していない。
    my $u = URI::Amazon::APA->new('https://webservices.amazon.co.jp');
    エラーメッセージ
    500 Can't connect to webservices.amazon.co.jp:80 (LWP::Protocol::https::Socket: SSL connect attempt failed error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol)
  • https のエンドポイントを使用するにはポートまで指定する必要がある。
  • testHttps.pl
    #!/bin/perl
    # test https scheme for URI and URI::Amazon::APA
    
    use strict;
    use warnings;
    use utf8;
    use Encode;
    use URI::Amazon::APA;
    use YAML::Syck qw(Dump);
    use open ':std' => ':locale';
    
    print "URI: ${URI::VERSION}\n";
    print "URI::Amazon::APA: ${URI::Amazon::APA::VERSION}\n";
    
    my @uris = qw(
        https://webservices.amazon.co.jp/onca/xml
        https://webservices.amazon.co.jp:443/onca/xml
    );
    
    foreach my $uri (@uris) {
        print "\n# ${uri}\n";
        print "URI:\n";
        print Dump( getProperty( URI->new($uri) ) ) . "\n";
        print "URI::Amazon::APA:\n";
        print Dump( getProperty( URI::Amazon::APA->new($uri) ) ) . "\n";
    }
    
    sub getProperty {
        my $u = shift;
        return {
            scheme => $u->scheme,
            secure => $u->secure,
            host   => $u->host,
            port   => $u->port,
        };
    }
  • テスト出力
    URI: 1.74
    URI::Amazon::APA: 0.05
    
    # https://webservices.amazon.co.jp/onca/xml
    URI:
    ---
    host: webservices.amazon.co.jp
    port: 443
    scheme: https
    secure: 1
    
    URI::Amazon::APA:
    must be http at ./testHttps.pl line 25.
    ---
    host: webservices.amazon.co.jp
    port: 80
    scheme: https
    secure: 0
    
    # https://webservices.amazon.co.jp:443/onca/xml
    URI:
    ---
    host: webservices.amazon.co.jp
    port: 443
    scheme: https
    secure: 1
    
    URI::Amazon::APA:
    must be http at ./testHttps.pl line 25.
    ---
    host: webservices.amazon.co.jp
    port: 443
    scheme: https
    secure: 0

リンク