product.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import os
  2. from sqlalchemy import Column, Integer, String, Text, DateTime, Float, create_engine
  3. from sqlalchemy.ext.declarative import declarative_base
  4. from sqlalchemy.orm import sessionmaker
  5. from datetime import datetime
  6. from config.settings import DATABASE_CONFIG
  7. Base = declarative_base()
  8. class Product(Base):
  9. __tablename__ = 'products'
  10. id = Column(Integer, primary_key=True, autoincrement=True)
  11. product_id = Column(String(100), unique=True, nullable=False, comment='来源平台的商品ID')
  12. name = Column(String(500), nullable=False, comment='商品名称')
  13. url = Column(Text, comment='商品链接')
  14. image_url = Column(Text, comment='商品图片链接')
  15. shop_name = Column(String(200), comment='店铺名称')
  16. platform = Column(String(50), nullable=False, comment='来源平台: taobao, jd, alibaba1688')
  17. category = Column(String(200), comment='商品分类')
  18. brand = Column(String(100), comment='品牌')
  19. is_wholesale = Column(Integer, default=0, comment='是否为批发商品: 0-否, 1-是')
  20. min_order_quantity = Column(Integer, comment='最小起订量(批发)')
  21. unit = Column(String(50), comment='单位')
  22. current_price = Column(Float, comment='当前价格')
  23. original_price = Column(Float, comment='原价')
  24. currency = Column(String(10), default='CNY', comment='货币单位')
  25. sales_volume = Column(Integer, comment='销量')
  26. rating = Column(Float, comment='评分')
  27. review_count = Column(Integer, comment='评论数')
  28. stock = Column(Integer, comment='库存')
  29. description = Column(Text, comment='商品描述')
  30. create_time = Column(DateTime, default=datetime.now, comment='创建时间')
  31. update_time = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment='更新时间')
  32. crawl_time = Column(DateTime, comment='最后爬取时间')
  33. def __repr__(self):
  34. return f"<Product(product_id='{self.product_id}', name='{self.name}', platform='{self.platform}')>"
  35. def to_dict(self):
  36. return {
  37. 'id': self.id,
  38. 'product_id': self.product_id,
  39. 'name': self.name,
  40. 'url': self.url,
  41. 'image_url': self.image_url,
  42. 'shop_name': self.shop_name,
  43. 'platform': self.platform,
  44. 'category': self.category,
  45. 'brand': self.brand,
  46. 'is_wholesale': self.is_wholesale,
  47. 'min_order_quantity': self.min_order_quantity,
  48. 'unit': self.unit,
  49. 'current_price': self.current_price,
  50. 'original_price': self.original_price,
  51. 'currency': self.currency,
  52. 'sales_volume': self.sales_volume,
  53. 'rating': self.rating,
  54. 'review_count': self.review_count,
  55. 'stock': self.stock,
  56. 'description': self.description,
  57. 'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if self.create_time else None,
  58. 'update_time': self.update_time.strftime('%Y-%m-%d %H:%M:%S') if self.update_time else None,
  59. 'crawl_time': self.crawl_time.strftime('%Y-%m-%d %H:%M:%S') if self.crawl_time else None
  60. }
  61. class PriceHistory(Base):
  62. __tablename__ = 'price_history'
  63. id = Column(Integer, primary_key=True, autoincrement=True)
  64. product_id = Column(String(100), nullable=False, comment='商品ID')
  65. price = Column(Float, nullable=False, comment='价格')
  66. original_price = Column(Float, comment='原价')
  67. currency = Column(String(10), default='CNY', comment='货币单位')
  68. platform = Column(String(50), nullable=False, comment='来源平台')
  69. source_url = Column(Text, comment='来源页面URL')
  70. crawl_time = Column(DateTime, default=datetime.now, comment='爬取时间')
  71. price_type = Column(String(50), default='retail', comment='价格类型: retail(零售), wholesale(批发)')
  72. min_quantity = Column(Integer, comment='最小起订量(批发价格)')
  73. max_quantity = Column(Integer, comment='最大起订量(批发价格)')
  74. def __repr__(self):
  75. return f"<PriceHistory(product_id='{self.product_id}', price={self.price}, crawl_time='{self.crawl_time}')>"
  76. def to_dict(self):
  77. return {
  78. 'id': self.id,
  79. 'product_id': self.product_id,
  80. 'price': self.price,
  81. 'original_price': self.original_price,
  82. 'currency': self.currency,
  83. 'platform': self.platform,
  84. 'source_url': self.source_url,
  85. 'crawl_time': self.crawl_time.strftime('%Y-%m-%d %H:%M:%S') if self.crawl_time else None,
  86. 'price_type': self.price_type,
  87. 'min_quantity': self.min_quantity,
  88. 'max_quantity': self.max_quantity
  89. }
  90. def get_engine():
  91. db_type = DATABASE_CONFIG.get('type', 'sqlite')
  92. if db_type == 'sqlite':
  93. sqlite_config = DATABASE_CONFIG.get('sqlite', {})
  94. db_path = sqlite_config.get('path', 'data/price_crawler.db')
  95. db_dir = os.path.dirname(db_path)
  96. if db_dir and not os.path.exists(db_dir):
  97. os.makedirs(db_dir, exist_ok=True)
  98. connection_string = f"sqlite:///{db_path}"
  99. return create_engine(connection_string, echo=False, connect_args={'check_same_thread': False})
  100. elif db_type == 'mysql':
  101. mysql_config = DATABASE_CONFIG.get('mysql', {})
  102. connection_string = (
  103. f"mysql+pymysql://{mysql_config.get('user', 'root')}:{mysql_config.get('password', '')}"
  104. f"@{mysql_config.get('host', 'localhost')}:{mysql_config.get('port', 3306)}/{mysql_config.get('database', 'price_crawler')}"
  105. f"?charset={mysql_config.get('charset', 'utf8mb4')}"
  106. )
  107. return create_engine(connection_string, echo=False)
  108. else:
  109. raise ValueError(f"不支持的数据库类型: {db_type}")
  110. def init_db():
  111. engine = get_engine()
  112. Base.metadata.create_all(engine)
  113. print("数据库初始化完成")
  114. def get_session():
  115. engine = get_engine()
  116. Session = sessionmaker(bind=engine)
  117. return Session()