こんにちは、”はふぃ”です。
ある日、「なんかアフィリエイトに繋がるサイトを一から作りたいなぁ」と思い、「商品のレビュー一覧が見れればその商品に対する世間の評価が知れて良いんじゃないか!!」という軽い気持ちで作り出しました。(すでにあるとか商品レビューには店舗への評価も含まれるから純粋な商品評価ではないなどは置いといて…笑)
その途中でYahoo!ショッピングの商品検索APIと商品レビュー検索APIを使ったので、任意の検索ワードで商品を検索し、レビューを取得するまでを書きます。
あ、ちなみにTypeSctiptは初めて使ったので温かい目で見てください。
概要
ユーザーが検索キーワードを入力
↓
商品検索APIを使ってキーワードから商品を検索
↓
検索結果の商品それぞれのレビューを商品レビュー検索APIを使って取得
※ Yahoo!JapanのWebAPIの利用には”アプリケーションID”が必要になるのでここから取得
使用技術
- Angular2
- TypeScript
内容
1.フォームを作成
< form.html >
<form [formGroup]="shoppingSearchForm" (ngSubmit)="onSubmit(shoppingSearchForm.value)" > <div class="field"> <label for="keyword">商品名</label> <input type="text" id="keyword" placeholder="iPhone X" [formControl]="shoppingSearchForm.controls['keyword']" > </div> <button class="ui button" type="submit" [disabled]="!shoppingSearchForm.valid">レビュー取得</button> </form>
2. 検索キーワードを使って商品を検索
【商品検索APIをたたく処理を記載したclass】
< yahoo-shopping-api.service.ts >
import { Observable } from 'rxjs/Rx'; import 'rxjs/add/operator/map'; @Injectable() export class YahooShoppingApiService { constructor(private _jsonp: Jsonp) { } /** * 商品検索API */ itemSearch (query: string, results: number) { // appid const appid = '[自分のappid]' // パラメータを設定 const searchParams = new URLSearchParams(); searchParams.set('appid', appid); searchParams.set('query', query || ''); searchParams.set('results', results.toString()); searchParams.set('callback', 'JSONP_CALLBACK'); // APIをたたく return this._jsonp .get('https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch', { search: searchParams }) .map(res => res.json()); } }
【上記の処理を使う側のclass】
ここではページ遷移先で取得した商品情報を使うためlocalStorageに情報を保存(ページ遷移の処理は省略)
< top/index.component.ts >
import { Component } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { YahooShoppingApiService } from '[YahooShoppingApiServiceのパス]'; @Component({ selector: 'top-index', templateUrl: './index.component.html', styleUrls: ['./index.component.css'], providers: [YahooShoppingApiService] }) export class IndexComponent { // 商品情報入力フォーム shoppingSearchForm: FormGroup; constructor( private fb: FormBuilder, private _yahooShoppingApiService: YahooShoppingApiService, ) { this.shoppingSearchForm = fb.group({ // 商品名 'keyword': ['', Validators.required] }); } // "レビュー取得"ボタンを押した時の処理 onSubmit(value: any): void { // 商品検索APIを使って、商品を検索する let itemList: object[] = [] this._yahooShoppingApiService .itemSearch(value.keyword, 50) .subscribe(data => { itemList = data.ResultSet[0].Result; }, null, () => { // localStrageに検索結果を保存 localStorage.setItem('yahooItemSearchResults', JSON.stringify(itemList)); }); } }
3. 取得した商品それぞれのレビューを取得
【商品レビュー検索APIをたたく処理を記載したclass】
< yahoo-shopping-api.service.ts >
・・・ /** * 商品検索API */ itemSearch (query: string, results: number) { ・・・ } /** * 商品レビュー検索API */ async reviewSearch (janCodes: number[]) { let reviews: object[] = []; // janコードを利用して、各商品に対するレビューを取得する for (let jan of janCodes) { // パラメータを設定 const searchParams = new URLSearchParams(); searchParams.set('appid', appid); searchParams.set('jan', jan.toString()); searchParams.set('callback', 'JSONP_CALLBACK'); // APIをたたく const itemReviews = await new Promise(resolve => { let results: object[] = [] this._jsonp .get('https://shopping.yahooapis.jp/ShoppingWebService/V1/json/reviewSearch', { search: searchParams }) .map(res => res.json()) .subscribe(data => { results = results.concat(data.ResultSet.Result); }, null, () => resolve(results)); }); reviews = reviews.concat(itemReviews); } return reviews; }
【上記の処理を使う側のclass】
< reviews/index.component.ts >
import { Component, OnInit } from '@angular/core'; import { YahooShoppingApiService } from '[YahooShoppingApiServiceのパス]'; import { Observable } from 'rxjs/Rx'; @Component({ selector: 'reviews-index', templateUrl: './index.component.html', styleUrls: ['./index.component.css'], providers: [YahooShoppingApiService] }) export class IndexComponent implements OnInit { // レビューの情報 reviews: object[] = []; constructor( private _yahooShoppingApiService: YahooShoppingApiService ) {} async ngOnInit() { // Yahoo商品検索APIの結果を取り出す const yahooItemSearchResult: object[] = JSON.parse(localStorage.getItem('yahooItemSearchResults')) || []; // それぞれのJANコードを取得 let janCodes: number[] = [] for (let i in yahooItemSearchResult) { if (yahooItemSearchResult[i]['JanCode']) { janCodes.push(yahooItemSearchResult[i]['JanCode']); } } // Yahoo商品レビューAPIからレビュー情報を取得する this.reviews = await this._yahooShoppingApiService.reviewSearch(janCodes); } }
苦労した点
- Yahoo!ショッピングのAPIを叩こうとするとクロスドメインの問題(CORS?)でアクセスできない
→ JSONPを利用することで解決
(参考:JSONP Example with Observables, Angular、Bootstrapなどの学習備忘録) - Observableの扱い
Observableからデータを取得する時に使用するsubscribeは以下のように使用する
Observable<any>.subscribe(data => { onNext, // データを取得した時の処理 onError, // エラー処理 onCompleted // データの取得が完了した時の処理 })
最後に
Yahoo!のWebAPIは商用利用が禁止なのでアフィリエイトと連携させての利用はできないっぽい!?
アフィリエイトもYahooのを使う場合は宣伝にもなるんだしいいじゃないかー泣