做个人图书管理系统,第一步不是做界面,也不是做导出,而是先把“扫到 ISBN 后能稳定查到书籍信息”这件事做扎实。
因为只要数据入口稳定了,后面的封面、分类、导出到 Markdown / Notion / Excel 都只是格式处理问题。

OK,开始之前,总结一下我用的方案

我的目标很明确:

  • 手机或电脑摄像头扫描 ISBN 条码
  • 自动获取书名、作者、出版社、出版日期、封面图等信息
  • 后续方便导出到 Markdown / Notion / Excel
  • 尽量保证稳定性和数据完整度

最终我先把“扫码 + 查书”这条链路打通,再往外扩展。

实战:扫码查书功能实现

开始之前,先看一下接口文档,确认参数和返回字段。
我这里用的是一个返回 JSON 的 ISBN 查询接口,接入方式比较直接,适合先做个人项目原型。

import cv2
from pyzbar.pyzbar import decode
import requests
import json

class BookScanner:
    def __init__(self, appcode):
        # 接口来源:ISBN图书查询(阿里云市场)
        # 文档地址:https://market.aliyun.com/detail/cmapi00065866
        self.appcode = appcode
        self.api_host = "https://tsisbn.market.alicloudapi.com"
        self.api_path = "/isbn/index"
    
    def scan_barcode(self):
        """打开摄像头,扫描 ISBN 条码"""
        cap = cv2.VideoCapture(0)
        print("请对准图书背面条码,按 Q 退出...")
        
        while True:
            ret, frame = cap.read()
            if not ret:
                break
                
            # 识别条码
            barcodes = decode(frame)
            for barcode in barcodes:
                isbn = barcode.data.decode('utf-8')
                # ISBN-13 必须是 978 开头
                if len(isbn) == 13 and isbn.startswith('978'):
                    cap.release()
                    cv2.destroyAllWindows()
                    return isbn
            
            cv2.imshow('Book Scanner', frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        
        cap.release()
        cv2.destroyAllWindows()
        return None
    
    def query_book(self, isbn):
        """通过 ISBN 查询图书信息"""
        url = f"{self.api_host}{self.api_path}?isbn={isbn}"
        headers = {"Authorization": f"APPCODE {self.appcode}"}
        
        try:
            response = requests.get(url, headers=headers, timeout=5)
            result = response.json()
            
            if result.get('code') == 1:
                data = result['data']
                return {
                    '书名': data.get('title'),
                    '作者': data.get('author'),
                    '出版社': data.get('publisher'),
                    '出版日期': data.get('pubdate'),
                    '页数': data.get('pages'),
                    '定价': data.get('price'),
                    'ISBN': data.get('isbn'),
                    '封面': data.get('img'),
                    '简介': data.get('summary', '')[:100] + '...'
                }
            else:
                print(f"查询失败:{result.get('msg')}")
                return None
                
        except Exception as e:
            print(f"请求异常:{e}")
            return None

# 使用示例
if __name__ == "__main__":
    # 从环境变量读取(安全做法)
    import os
    APPCODE = os.getenv('ISBN_APPCODE', '你的AppCode')
    
    scanner = BookScanner(APPCODE)
    
    # 方式 1:扫码
    # isbn = scanner.scan_barcode()
    
    # 方式 2:直接输入 ISBN(测试用)
    isbn = "9787115545138"
    
    if isbn:
        book = scanner.query_book(isbn)
        if book:
            print("\n" + "="*40)
            for k, v in book.items():
                print(f"{k}: {v}")
            print("="*40)

这段代码里几个关键点

  • scan_barcode() 负责打开摄像头并识别条码,识别到符合条件的 ISBN 后直接返回
  • query_book() 负责把 ISBN 传给接口,并把返回结果整理成统一的字典格式
  • timeout=5 用来避免接口请求时间过长,防止程序一直卡住
  • summary 做了截断处理,避免简介太长,方便后续展示
  • AppCode 建议通过环境变量读取,后期部署或换机器时更方便

实际使用时的建议

  • 先用“直接输入 ISBN”的方式调通接口,再接摄像头识别
  • 条码识别对光线和角度有要求,测试时尽量让书脊/背面条码清晰
  • 如果后面要做导出,建议统一返回字典结构,这样写 CSV、Excel 或 Markdown 都很方便
  • 个人项目优先追求稳定,不要一开始就把功能铺太大

小结

这一步做完之后,个人图书管理系统最核心的“数据获取”就跑通了。
后面不管是做:

  • 图书入库
  • 本地搜索
  • 分类管理
  • 导出到 Excel / Notion
  • 生成书单

都可以在这个结果字典的基础上继续扩展。

更多推荐