我的个人博客

在Node.js中抓取和解析Goodreads用户图书数据

Published on
Published on
/3 mins read/---

由于Goodreads不再支持通过其API获取用户的图书数据, 我决定使用RSS源抓取用户的图书数据,并在Node.js中进行解析。

Goodreads API

这里的思路是使用rss-parser包来解析RSS源并提取图书数据。

goodreads.ts
import Parser from 'rss-parser'
import type { GoodreadsBook } from '~/types'
 
let parser = new Parser<{ [key: string]: any }, GoodreadsBook>({
  customFields: {
    // 定义你想从RSS源中提取的所有自定义字段
    // 这里我列出了Goodreads RSS源中所有可用的字段
    item: [
      'guid',
      'pubDate',
      'title',
      'link',
      'book_id',
      'book_image_url',
      'book_small_image_url',
      'book_medium_image_url',
      'book_large_image_url',
      'book_description',
      'author_name',
      'isbn',
      'user_name',
      'user_rating',
      'user_read_at',
      'user_date_added',
      'user_date_created',
      'user_shelves',
      'user_review',
      'average_rating',
      'book_published',
    ],
  },
})

然后你可以使用parser对象从RSS源获取数据,并根据需要进行处理。

goodreads.ts
const GOODREADS_RSS_FEED_URL = '<YOUR_GOODREADS_RSS_FEED_URL>'
 
export async function fetchGoodreadsBooks() {
  if (GOODREADS_RSS_FEED_URL) {
    try {
      let data = await parser.parseURL(GOODREADS_RSS_FEED_URL)
      // 所有图书数据将存储在`data.items`数组中
      // 根据需要使用解析后的数据,例如,你可以将其写入JSON文件:
      writeFileSync(`./json/books.json`, JSON.stringify(data.items))
    } catch (error) {
      console.error(`获取Goodreads RSS源时出错:${error.message}`)
    }
  } else {
    console.log('📚 未找到Goodreads RSS源。')
  }
}

NOTE

你可以通过访问Goodreads用户的个人资料,导航到书架页面并复制RSS源URL来获取该用户的RSS源URL。 例如,这是我的书架页面:https://www.goodreads.com/review/list/179720035

现在你已经有了数据,在存储或在应用程序中使用之前,你可能需要美化它们, 因为数据是以原始格式存储的。

types.ts
let data = await parser.parseURL(/* GOODREADS_RSS_FEED_URL */)
// 遍历`data.items`数组来美化数据
for (let book of data.items) {
  book.content = book.content.replace(/\n/g, '').replace(/\s\s+/g, ' ') // 移除换行符
  book.book_description = book.book_description
    .replace(/<[^>]*(>|$)/g, '') // 移除HTML标签
    .replace(/\s\s+/g, ' ') // 将多个空格替换为单个空格
    .replace(/^["|"]|["|"]$/g, '') // 移除开头和结尾的引号
    .replace(/\.([a-zA-Z0-9])/g, '. $1') // 在句点后添加空格
}
// 根据需要使用解析和美化后的数据...

GoodreadsBook类型定义如下:

types.ts
export type GoodreadsBook = {
  guid: string
  pubDate: string
  title: string
  link: string
  book_id: string
  book_image_url: string
  book_small_image_url: string
  book_medium_image_url: string
  book_large_image_url: string
  book_description: string
  author_name: string
  isbn: string
  user_name: string
  user_rating: string
  user_read_at: string
  user_date_added: string
  user_date_created: string
  user_shelves: string
  user_review: string
  average_rating: number
  book_published: string
  content: string
}

注意事项

如果你在Goodreads上更新了你的图书,Goodreads RSS源不会立即更新。 你可能需要等待几个小时才能获取最新数据。

愉快地抓取数据吧!