golang访问MyAnimeList API的客户端插件库go-myanimelist的使用

golang访问MyAnimeList API的客户端插件库go-myanimelist的使用

项目介绍

go-myanimelist 是一个用于访问 MyAnimeList API v2 的 Go 客户端库。该项目已更新以支持 MyAnimeList API v2,并且自2017年3月起被收录在 awesome-go 中。

安装

使用以下命令安装该包:

go get github.com/nstratos/go-myanimelist/mal

使用方式

导入包:

import "github.com/nstratos/go-myanimelist/mal"

首先创建一个新的 mal 客户端:

c := mal.NewClient(nil)

然后使用客户端的服务(User、Anime、Manga 和 Forum)来访问不同的 MyAnimeList API 方法。

认证

访问公开信息

要访问公共信息,你需要在请求中添加 X-MAL-CLIENT-ID 头部。可以通过创建一个带有自定义传输的 http.Client 来实现:

type clientIDTransport struct {
	Transport http.RoundTripper
	ClientID  string
}

func (c *clientIDTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if c.Transport == nil {
		c.Transport = http.DefaultTransport
	}
	req.Header.Add("X-MAL-CLIENT-ID", c.ClientID)
	return c.Transport.RoundTrip(req)
}

func main() {
	publicInfoClient := &http.Client{
		// 从 https://myanimelist.net/apiconfig 创建客户端ID
		Transport: &clientIDTransport{ClientID: "<Your application client ID>"},
	}

	c := mal.NewClient(publicInfoClient)
	// ...
}

使用 OAuth2 认证

推荐使用 golang.org/x/oauth2 包。完成 OAuth2 流程后,你将获得一个包含访问令牌、刷新令牌和过期日期的 oauth2 令牌。

const storedToken = `
{
	"token_type": "Bearer",
	"access_token": "yourAccessToken",
	"refresh_token": "yourRefreshToken",
	"expiry": "2021-06-01T16:12:56.1319122Z"
}`

oauth2Token := new(oauth2.Token)
_ = json.Unmarshal([]byte(storedToken), oauth2Token)

// 从 https://myanimelist.net/apiconfig 创建客户端ID和密钥
//
// 如果选择应用类型为"other",则密钥目前是可选的
oauth2Conf := &oauth2.Config{
    ClientID:     "<Enter your registered MyAnimeList.net application client ID>",
    ClientSecret: "<Enter your registered MyAnimeList.net application client secret>",
    Endpoint: oauth2.Endpoint{
        AuthURL:   "https://myanimelist.net/v1/oauth2/authorize",
        TokenURL:  "https://myanimelist.net/v1/oauth2/token",
        AuthStyle: oauth2.AuthStyleInParams,
    },
}

oauth2Client := oauth2Conf.Client(ctx, oauth2Token)

// oauth2Client 将在令牌过期时刷新令牌
c := mal.NewClient(oauth2Client)

完整示例

以下是一个完整的示例,展示如何使用 go-myanimelist 库访问 MyAnimeList API:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/nstratos/go-myanimelist/mal"
	"golang.org/x/oauth2"
)

func main() {
	// 使用 OAuth2 认证
	const storedToken = `
	{
		"token_type": "Bearer",
		"access_token": "yourAccessToken",
		"refresh_token": "yourRefreshToken",
		"expiry": "2021-06-01T16:12:56.1319122Z"
	}`

	oauth2Token := new(oauth2.Token)
	_ = json.Unmarshal([]byte(storedToken), oauth2Token)

	oauth2Conf := &oauth2.Config{
		ClientID:     "<Your Client ID>",
		ClientSecret: "<Your Client Secret>",
		Endpoint: oauth2.Endpoint{
			AuthURL:   "https://myanimelist.net/v1/oauth2/authorize",
			TokenURL:  "https://myanimelist.net/v1/oauth2/token",
			AuthStyle: oauth2.AuthStyleInParams,
		},
	}

	ctx := context.Background()
	oauth2Client := oauth2Conf.Client(ctx, oauth2Token)

	// 创建客户端
	c := mal.NewClient(oauth2Client)

	// 获取用户信息
	user, _, err := c.User.MyInfo(ctx)
	if err != nil {
		fmt.Printf("Error getting user info: %v\n", err)
		return
	}
	fmt.Printf("User: %+v\n", user)

	// 搜索动漫
	animeList, _, err := c.Anime.List(ctx, "hokuto no ken",
		mal.Fields{"rank", "popularity", "my_list_status"},
		mal.Limit(5),
	)
	if err != nil {
		fmt.Printf("Error searching anime: %v\n", err)
		return
	}
	fmt.Println("Anime search results:")
	for _, a := range animeList {
		fmt.Printf("- %s (Rank: %d, Popularity: %d)\n", a.Title, a.Rank, a.Popularity)
	}

	// 获取动漫详情
	animeDetails, _, err := c.Anime.Details(ctx, 967,
		mal.Fields{
			"alternative_titles",
			"media_type",
			"num_episodes",
			"start_season",
			"source",
			"genres",
			"studios",
			"average_episode_duration",
		},
	)
	if err != nil {
		fmt.Printf("Error getting anime details: %v\n", err)
		return
	}
	fmt.Printf("Anime details: %+v\n", animeDetails)

	// 更新我的动漫列表状态
	_, _, err = c.Anime.UpdateMyListStatus(ctx, 967,
		mal.AnimeStatusWatching,
		mal.NumEpisodesWatched(73),
		mal.Score(8),
		mal.Comments("You wa shock!"),
		mal.StartDate(time.Date(2022, 02, 20, 0, 0, 0, 0, time.UTC)),
		mal.FinishDate(time.Time{}), // 移除现有日期
	)
	if err != nil {
		fmt.Printf("Error updating anime list: %v\n", err)
		return
	}
	fmt.Println("Successfully updated anime list")
}

更多功能

该库还支持以下功能:

  • 获取用户动漫/漫画列表
  • 获取动漫/漫画排名
  • 删除列表项等

测试

运行单元测试:

go test -cover

运行集成测试:

go test --client-id='<your app client ID>' --oauth2-token='<your oauth2 token>'

许可证

MIT


更多关于golang访问MyAnimeList API的客户端插件库go-myanimelist的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang访问MyAnimeList API的客户端插件库go-myanimelist的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用go-myanimelist访问MyAnimeList API

go-myanimelist 是一个非官方的Golang客户端库,用于访问MyAnimeList API。下面我将介绍如何使用这个库来与MyAnimeList API交互。

安装

首先安装go-myanimelist库:

go get github.com/nstratos/go-myanimelist/mal

认证设置

要使用MyAnimeList API,你需要先注册一个客户端ID。可以在MyAnimeList开发者页面申请。

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/nstratos/go-myanimelist/mal"
)

func main() {
	// 从环境变量获取客户端ID
	clientID := os.Getenv("MAL_CLIENT_ID")
	if clientID == "" {
		log.Fatal("请设置MAL_CLIENT_ID环境变量")
	}

	// 创建客户端
	client, err := mal.NewClient(clientID)
	if err != nil {
		log.Fatal(err)
	}
}

基本使用示例

1. 搜索动漫

func searchAnime(client *mal.Client, query string) {
	ctx := context.Background()

	// 搜索动漫
	result, _, err := client.Anime.Search(ctx, query,
		mal.Fields{"rank", "popularity", "mean", "media_type", "num_episodes"},
		mal.Limit(5),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("搜索结果:")
	for _, anime := range result {
		fmt.Printf("ID: %5d, 标题: %-30s, 评分: %.2f, 集数: %d\n", 
			anime.ID, anime.Title, anime.Mean, anime.NumEpisodes)
	}
}

2. 获取动漫详情

func getAnimeDetails(client *mal.Client, animeID int) {
	ctx := context.Background()

	// 获取动漫详情
	anime, _, err := client.Anime.Details(ctx, animeID,
		mal.Fields{
			"id", "title", "main_picture", "alternative_titles", 
			"start_date", "end_date", "synopsis", "mean", "rank", 
			"popularity", "num_list_users", "num_scoring_users", 
			"nsfw", "created_at", "updated_at", "media_type", 
			"status", "genres", "my_list_status", "num_episodes", 
			"start_season", "broadcast", "source", "average_episode_duration", 
			"rating", "pictures", "background", "related_anime", 
			"related_manga", "recommendations", "studios", "statistics",
		},
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("动漫详情:\nID: %d\n标题: %s\n类型: %s\n状态: %s\n评分: %.2f\n简介: %s\n",
		anime.ID, anime.Title, anime.MediaType, anime.Status, anime.Mean, anime.Synopsis)
}

3. 获取用户动漫列表

func getUserAnimeList(client *mal.Client, username string) {
	ctx := context.Background()

	// 获取用户动漫列表
	list, _, err := client.Anime.List(ctx, username,
		mal.Fields{"list_status"},
		mal.Limit(10),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%s的动漫列表:\n", username)
	for _, anime := range list {
		status := anime.ListStatus.Status
		if status == "" {
			status = "未观看"
		}
		fmt.Printf("%s - %s (进度: %d/%d)\n", 
			anime.Anime.Title, status, 
			anime.ListStatus.NumEpisodesWatched, anime.Anime.NumEpisodes)
	}
}

4. 更新用户动漫列表状态

func updateAnimeStatus(client *mal.Client, animeID int) {
	ctx := context.Background()

	// 需要OAuth2认证
	// 这里假设你已经有了OAuth2 token
	// 实际使用中需要实现OAuth2流程获取token

	// 更新动漫状态
	_, err := client.Anime.UpdateMyListStatus(ctx, animeID,
		mal.AnimeStatusWatching,
		mal.NumEpisodesWatched(5),
		mal.Score(8),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("动漫状态更新成功")
}

OAuth2认证流程

要更新用户数据,需要OAuth2认证。以下是基本流程:

func oauth2Example(clientID string) {
	// 创建OAuth2配置
	oauth2Config := &oauth2.Config{
		ClientID:    clientID,
		Endpoint:    mal.Endpoint,
		RedirectURL: "urn:ietf:wg:oauth:2.0:oob", // 用于CLI应用
	}

	// 生成授权URL
	authURL := oauth2Config.AuthCodeURL("state", oauth2.AccessTypeOffline)
	fmt.Printf("请访问以下URL授权:\n%s\n", authURL)

	// 用户授权后获取code
	fmt.Print("请输入授权码: ")
	var code string
	if _, err := fmt.Scan(&code); err != nil {
		log.Fatal(err)
	}

	// 交换code获取token
	ctx := context.Background()
	token, err := oauth2Config.Exchange(ctx, code)
	if err != nil {
		log.Fatal(err)
	}

	// 使用token创建认证客户端
	authClient := oauth2Config.Client(ctx, token)
	client := mal.NewWithClient(authClient)

	// 现在可以使用认证后的client进行操作...
}

完整示例

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/nstratos/go-myanimelist/mal"
	"golang.org/x/oauth2"
)

func main() {
	clientID := os.Getenv("MAL_CLIENT_ID")
	if clientID == "" {
		log.Fatal("请设置MAL_CLIENT_ID环境变量")
	}

	// 创建客户端
	client, err := mal.NewClient(clientID)
	if err != nil {
		log.Fatal(err)
	}

	// 搜索示例
	searchAnime(client, "Attack on Titan")

	// 获取详情示例
	// getAnimeDetails(client, 16498) // Shingeki no Kyojin ID

	// 用户列表示例
	// getUserAnimeList(client, "some_username")

	// OAuth2示例 (需要实际实现)
	// oauth2Example(clientID)
}

注意事项

  1. MyAnimeList API有请求限制,请合理控制请求频率
  2. 敏感操作需要OAuth2认证
  3. 字段选择使用mal.Fields可以优化API响应大小
  4. 错误处理在实际应用中很重要,示例中简化了错误处理

这个库提供了对MyAnimeList API的全面覆盖,你可以根据需要扩展上述示例来实现更多功能。

回到顶部