golang TripAdvisor API接口封装与调用插件库TripAdvisor的使用

Golang TripAdvisor API接口封装与调用插件库TripAdvisor的使用

简介

这是一个用于Golang的TripAdvisor API封装库,可以方便地调用TripAdvisor API获取地点信息和评论数据。

安装

go get "github.com/mrbenosborne/tripadvisor-golang"

配置选项

SetKey

设置用于所有HTTP请求的TripAdvisor API密钥。

SetKey(string)

SetEndpoint

设置TripAdvisor端点,目前仅支持TripAdvisor API的第2版。

SetEndpoint(string)

SetLanguageCode

设置TripAdvisor响应的语言代码,支持的代码列表可以参考TripAdvisor API文档。

SetLanguageCode(string)

SetTimeout

设置所有HTTP请求的超时时间,默认为30秒。

SetTimeout(time.Duration)

使用示例

package main

import (
	"context"
	"log"

	"github.com/mrbenosborne/tripadvisor-golang/pkg/tripadvisor"
)

func main() {

    // 创建新客户端
	tClient := tripadvisor.New(
		tripadvisor.SetKey("XXXXXXXXXXXXXXXXXXXXXX"),
		tripadvisor.SetLanguageCode("en_UK"),
    )

    // 获取地点评论(碎片大厦)
	response, err := tClient.Location(context.Background(), 3539289)
	if err != nil {
		panic(err)
	}

    // 打印地点数据
	log.Printf("%s - 总评论数: %s\n", response.Name, response.NumReviews)
	for _, review := range response.Reviews {
		log.Printf("评论:\n\t%s\n", review.Content)
	}
}

示例响应

以下是Location响应的JSON格式示例输出:

{
  "name": "The View from The Shard",
  "num_reviews": "17349",
  "category": {
    "name": "attraction",
    "localized_name": "Attraction"
  },
  "address_obj": {
    "street1": "Joiner Street",
    "city": "London",
    "country": "United Kingdom",
    "postalcode": "SE1",
    "address_string": "Joiner Street, London SE1 England"
  },
  "latitude": "51.5045",
  "longitude": "-0.0865",
  "rating": "4.5",
  "location_id": "3539289",
  "trip_types": [
    {
      "name": "business",
      "value": "318",
      "localized_name": "Business"
    },
    {
      "name": "couples",
      "value": "7458",
      "localized_name": "Couples"
    },
    {
      "name": "solo",
      "value": "960",
      "localized_name": "Solo travel"
    },
    {
      "name": "family",
      "value": "3426",
      "localized_name": "Family"
    },
    {
      "name": "friends",
      "value": "3138",
      "localized_name": "Friends getaway"
    }
  ],
  "reviews": [
    {
      "id": "666623404",
      "lang": "en",
      "location_id": "3539289",
      "published_date": "2019-04-15T03:54:07-0400",
      "rating": 5,
      "helpful_votes": "1",
      "rating_image_url": "https://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/s5.0-20236-5.svg",
      "url": "https://www.tripadvisor.com/ShowUserReviews-g186338-d3539289-r666623404-The_View_from_The_Shard-London_England.html?m=20236#review666623404",
      "travel_date": "2019-03",
      "text": "Visiting The Shard (top level) is a must do in London, especially on not cloudy days.   Wonderful view all around (attractions even seem to be small from there).  No cheap (+- 30 GBP per person, but...",
      "user": {
        "username": "WimD94",
        "user_location": {}
      },
      "title": "Beautiful view on sunny days"
    },
    {
      "id": "666436956",
      "lang": "en",
      "location_id": "3539289",
      "published_date": "2019-04-14T11:13:08-0400",
      "rating": 5,
      "helpful_votes": "1",
      "rating_image_url": "https://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/s5.0-20236-5.svg",
      "url": "https://www.tripadvisor.com/ShowUserReviews-g186338-d3539289-r666436956-The_View_from_The_Shard-London_England.html?m=20236#review666436956",
      "trip_type": "Business",
      "travel_date": "2019-02",
      "text": "I visited IntechOpen Office at The Shard and they could not have chosen a better workplace.  The views from the top floor were spectacular.",
      "user": {
        "username": "MariaLorna1",
        "user_location": {
          "name": "Davis, California",
          "id": "32283"
        }
      },
      "title": "Beaautiful"
    }
  ],
  "percent_recommended": 82,
  "review_rating_count": {
    "1": "318",
    "2": "477",
    "3": "1802",
    "4": "4798",
    "5": "9680"
  },
  "photo_count": "11780",
  "location_string": "London, England"
}

更多关于golang TripAdvisor API接口封装与调用插件库TripAdvisor的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang TripAdvisor API接口封装与调用插件库TripAdvisor的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


TripAdvisor API接口封装与调用插件库

TripAdvisor是一个全球知名的旅游评论和预订平台,提供丰富的API接口供开发者使用。下面我将介绍如何在Go语言中封装和调用TripAdvisor API。

1. 准备工作

首先,你需要在TripAdvisor开发者门户(https://developer-tripadvisor.com/)注册账号并获取API密钥。

2. 基础封装

以下是一个基础的TripAdvisor API封装示例:

package tripadvisor

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
)

const (
	baseURL = "https://api.tripadvisor.com/api/partner/2.0/"
)

type Client struct {
	apiKey     string
	httpClient *http.Client
}

func NewClient(apiKey string) *Client {
	return &Client{
		apiKey:     apiKey,
		httpClient: &http.Client{},
	}
}

func (c *Client) makeRequest(endpoint string, params map[string]string) ([]byte, error) {
	// 构建请求URL
	reqURL, err := url.Parse(baseURL + endpoint)
	if err != nil {
		return nil, err
	}

	// 添加查询参数
	query := reqURL.Query()
	query.Set("key", c.apiKey)
	for key, value := range params {
		query.Set(key, value)
	}
	reqURL.RawQuery = query.Encode()

	// 发送请求
	resp, err := c.httpClient.Get(reqURL.String())
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("API request failed with status code: %d", resp.StatusCode)
	}

	// 读取响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}

3. 常用API方法封装

3.1 地点搜索

type Location struct {
	LocationID string  `json:"location_id"`
	Name       string  `json:"name"`
	Latitude   float64 `json:"latitude"`
	Longitude  float64 `json:"longitude"`
	Address    string  `json:"address_obj"`
}

type LocationSearchResponse struct {
	Data []Location `json:"data"`
}

func (c *Client) SearchLocations(query string, limit int) ([]Location, error) {
	params := map[string]string{
		"searchQuery": query,
		"limit":       fmt.Sprintf("%d", limit),
	}

	body, err := c.makeRequest("location/search", params)
	if err != nil {
		return nil, err
	}

	var response LocationSearchResponse
	err = json.Unmarshal(body, &response)
	if err != nil {
		return nil, err
	}

	return response.Data, nil
}

3.2 获取地点详情

type LocationDetails struct {
	LocationID  string  `json:"location_id"`
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Rating      float64 `json:"rating"`
	RatingImage string  `json:"rating_image_url"`
	Address     string  `json:"address"`
	Phone       string  `json:"phone"`
	Website     string  `json:"website"`
	PhotoCount  int     `json:"photo_count"`
	ReviewCount int     `json:"num_reviews"`
}

func (c *Client) GetLocationDetails(locationID string) (*LocationDetails, error) {
	endpoint := fmt.Sprintf("location/%s", locationID)
	body, err := c.makeRequest(endpoint, nil)
	if err != nil {
		return nil, err
	}

	var details LocationDetails
	err = json.Unmarshal(body, &details)
	if err != nil {
		return nil, err
	}

	return &details, nil
}

3.3 获取地点评论

type Review struct {
	ID          string  `json:"review_id"`
	Rating      float64 `json:"rating"`
	Title       string  `json:"title"`
	Text        string  `json:"text"`
	UserName    string  `json:"user_name"`
	UserAvatar  string  `json:"user_avatar"`
	PublishDate string  `json:"published_date"`
}

type ReviewsResponse struct {
	Data []Review `json:"data"`
}

func (c *Client) GetLocationReviews(locationID string, limit int) ([]Review, error) {
	endpoint := fmt.Sprintf("location/%s/reviews", locationID)
	params := map[string]string{
		"limit": fmt.Sprintf("%d", limit),
	}

	body, err := c.makeRequest(endpoint, params)
	if err != nil {
		return nil, err
	}

	var response ReviewsResponse
	err = json.Unmarshal(body, &response)
	if err != nil {
		return nil, err
	}

	return response.Data, nil
}

4. 使用示例

package main

import (
	"fmt"
	"log"
	"yourpackage/tripadvisor"
)

func main() {
	// 初始化客户端
	apiKey := "your_api_key_here"
	client := tripadvisor.NewClient(apiKey)

	// 搜索地点
	locations, err := client.SearchLocations("Eiffel Tower", 5)
	if err != nil {
		log.Fatalf("Error searching locations: %v", err)
	}

	// 打印搜索结果
	for _, loc := range locations {
		fmt.Printf("Found location: %s (ID: %s)\n", loc.Name, loc.LocationID)
	}

	// 获取第一个地点的详情
	if len(locations) > 0 {
		details, err := client.GetLocationDetails(locations[0].LocationID)
		if err != nil {
			log.Fatalf("Error getting location details: %v", err)
		}
		fmt.Printf("\nDetails for %s:\n", details.Name)
		fmt.Printf("Rating: %.1f\n", details.Rating)
		fmt.Printf("Reviews: %d\n", details.ReviewCount)
		fmt.Printf("Description: %s\n", details.Description)

		// 获取评论
		reviews, err := client.GetLocationReviews(locations[0].LocationID, 3)
		if err != nil {
			log.Fatalf("Error getting reviews: %v", err)
		}

		fmt.Println("\nRecent Reviews:")
		for _, review := range reviews {
			fmt.Printf("\n%s - %s\n", review.UserName, review.Title)
			fmt.Printf("Rating: %.1f\n", review.Rating)
			fmt.Printf("%s\n", review.Text)
		}
	}
}

5. 高级功能

5.1 添加缓存

type CachedClient struct {
	client    *Client
	cache     map[string][]byte
	cacheTTL  time.Duration
	lastClean time.Time
}

func NewCachedClient(apiKey string, ttl time.Duration) *CachedClient {
	return &CachedClient{
		client:    NewClient(apiKey),
		cache:     make(map[string][]byte),
		cacheTTL:  ttl,
		lastClean: time.Now(),
	}
}

func (c *CachedClient) makeRequest(endpoint string, params map[string]string) ([]byte, error) {
	// 生成缓存键
	cacheKey := endpoint + "?" + url.Values(params).Encode()
	
	// 检查缓存
	if data, ok := c.cache[cacheKey]; ok {
		return data, nil
	}
	
	// 清理过期缓存
	if time.Since(c.lastClean) > c.cacheTTL {
		c.cache = make(map[string][]byte)
		c.lastClean = time.Now()
	}
	
	// 调用原始API
	data, err := c.client.makeRequest(endpoint, params)
	if err != nil {
		return nil, err
	}
	
	// 存入缓存
	c.cache[cacheKey] = data
	
	return data, nil
}

5.2 错误处理增强

type APIError struct {
	StatusCode int
	Message    string
}

func (e APIError) Error() string {
	return fmt.Sprintf("API error (status %d): %s", e.StatusCode, e.Message)
}

// 修改makeRequest方法
func (c *Client) makeRequest(endpoint string, params map[string]string) ([]byte, error) {
	// ...之前的代码...
	
	if resp.StatusCode != http.StatusOK {
		errorBody, _ := ioutil.ReadAll(resp.Body)
		var apiErr struct {
			Message string `json:"message"`
		}
		json.Unmarshal(errorBody, &apiErr)
		
		return nil, APIError{
			StatusCode: resp.StatusCode,
			Message:    apiErr.Message,
		}
	}
	
	// ...之后的代码...
}

6. 最佳实践

  1. 限流处理:TripAdvisor API有调用频率限制,建议实现限流机制
  2. 重试机制:对于临时性错误,实现自动重试
  3. 日志记录:记录API调用情况和错误
  4. 单元测试:为关键功能编写单元测试
  5. 上下文支持:添加context支持以便取消长时间运行的请求

7. 总结

本文介绍了如何在Go中封装TripAdvisor API,包括基础封装、常用API方法实现、缓存和错误处理增强等。通过合理的封装,可以使API调用更加简洁和安全,同时提高代码的可维护性。

你可以根据实际需求扩展这个基础封装,添加更多API端点支持或增强功能。记得在生产环境中添加适当的错误处理、日志记录和监控机制。

回到顶部