From 30a03efd3b2b98e256862f7cedf00ab6986b2e77 Mon Sep 17 00:00:00 2001 From: xingc Date: Tue, 6 May 2025 21:51:02 +0800 Subject: [PATCH] =?UTF-8?q?fix(card):=20=E6=96=B0=E5=A2=9E=E6=B8=A0?= =?UTF-8?q?=E9=81=93`cic`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- alembic/versions/6bd2808b89b3_fix_product.py | 42 ++++++++++++++ .../e2a204afe670_new_add_support_platform.py | 48 ++++++++++++++++ core/base/schema.py | 2 + core/db/models.py | 4 +- core/routers/card/scraper.py | 55 ++++++++++++++++++- 5 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 alembic/versions/6bd2808b89b3_fix_product.py create mode 100644 alembic/versions/e2a204afe670_new_add_support_platform.py diff --git a/alembic/versions/6bd2808b89b3_fix_product.py b/alembic/versions/6bd2808b89b3_fix_product.py new file mode 100644 index 0000000..0666ab5 --- /dev/null +++ b/alembic/versions/6bd2808b89b3_fix_product.py @@ -0,0 +1,42 @@ +"""fix product + +Revision ID: 6bd2808b89b3 +Revises: 2d63d72e671a +Create Date: 2025-05-06 17:26:55.406210 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision: str = '6bd2808b89b3' +down_revision: Union[str, None] = '2d63d72e671a' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('system_chats', 'is_deleted', + existing_type=mysql.TINYINT(display_width=4), + nullable=False) + op.alter_column('system_users', 'avatar_url', + existing_type=mysql.VARCHAR(length=500), + nullable=True, + existing_comment='头像链接') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('system_users', 'avatar_url', + existing_type=mysql.VARCHAR(length=500), + nullable=False, + existing_comment='头像链接') + op.alter_column('system_chats', 'is_deleted', + existing_type=mysql.TINYINT(display_width=4), + nullable=True) + # ### end Alembic commands ### diff --git a/alembic/versions/e2a204afe670_new_add_support_platform.py b/alembic/versions/e2a204afe670_new_add_support_platform.py new file mode 100644 index 0000000..1ed7522 --- /dev/null +++ b/alembic/versions/e2a204afe670_new_add_support_platform.py @@ -0,0 +1,48 @@ +"""new add support platform + +Revision ID: e2a204afe670 +Revises: 6bd2808b89b3 +Create Date: 2025-05-06 21:36:32.322778 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision: str = 'e2a204afe670' +down_revision: Union[str, None] = '6bd2808b89b3' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('system_cache_cards', 'source', + existing_type=mysql.ENUM('PSA', 'BGS', 'CGC', 'GBTC', 'CCG', 'BCTC', 'CIC'), + comment='数据来源:PSA、BGS、CGC、GBTC、CCG、BCTC、CIC', + existing_comment='数据来源:PSA、BGS、CGC、GBTC、CCG、BCTC', + existing_nullable=False) + op.alter_column('system_cards', 'source', + existing_type=mysql.ENUM('PSA', 'BGS', 'CGC', 'GBTC', 'CCG', 'BCTC', 'CIC', 'OTHER'), + comment='来源,PSA、BGS、CGC、GBTC、CCG、BCTC、CIC :采集 、OTHER:自定义', + existing_comment='来源,PSA、BGS、CGC、GBTC、CCG、BCTC :采集 、OTHER:自定义', + existing_nullable=False) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('system_cards', 'source', + existing_type=mysql.ENUM('PSA', 'BGS', 'CGC', 'GBTC', 'CCG', 'BCTC', 'OTHER'), + comment='来源,PSA、BGS、CGC、GBTC、CCG、BCTC :采集 、OTHER:自定义', + existing_comment='来源,PSA、BGS、CGC、GBTC、CCG、BCTC、CIC :采集 、OTHER:自定义', + existing_nullable=False) + op.alter_column('system_cache_cards', 'source', + existing_type=mysql.ENUM('PSA', 'BGS', 'CGC', 'GBTC', 'CCG', 'BCTC'), + comment='数据来源:PSA、BGS、CGC、GBTC、CCG、BCTC', + existing_comment='数据来源:PSA、BGS、CGC、GBTC、CCG、BCTC、CIC', + existing_nullable=False) + # ### end Alembic commands ### diff --git a/core/base/schema.py b/core/base/schema.py index 73ba0c1..4f9747e 100644 --- a/core/base/schema.py +++ b/core/base/schema.py @@ -32,6 +32,7 @@ class SupportPlatformType(enum.Enum): GBTC = 'gbtc' CCG = 'ccg' BCTC = 'bctc' + CIC = 'cic' class PlatformSourceType(enum.Enum): @@ -41,6 +42,7 @@ class PlatformSourceType(enum.Enum): GBTC = 'gbtc' CCG = 'ccg' BCTC = 'bctc' + CIC = 'cic' OTHER = 'other' diff --git a/core/db/models.py b/core/db/models.py index eeb3554..0ae6ee4 100644 --- a/core/db/models.py +++ b/core/db/models.py @@ -154,7 +154,7 @@ class Card(BaseModel, DateModel): ) source: Mapped[str] = mapped_column( Enum(base_schema.PlatformSourceType, inherit_schema=True), - comment='来源,PSA、BGS、CGC、GBTC、CCG、BCTC :采集 、OTHER:自定义' + comment='来源,PSA、BGS、CGC、GBTC、CCG、BCTC、CIC :采集 、OTHER:自定义' ) diy_source: Mapped[str] = mapped_column(String(50), nullable=True, comment='自定义品牌名') @@ -207,7 +207,7 @@ class SearchCardCache(BaseModel, DateModel): raw_data: Mapped[dict] = mapped_column(JSON, comment='原始数据') source: Mapped[str] = mapped_column( Enum(base_schema.SupportPlatformType, inherit_schema=True), - comment='数据来源:PSA、BGS、CGC、GBTC、CCG、BCTC' + comment='数据来源:PSA、BGS、CGC、GBTC、CCG、BCTC、CIC' ) diff --git a/core/routers/card/scraper.py b/core/routers/card/scraper.py index 0ea7fd7..da13fa0 100644 --- a/core/routers/card/scraper.py +++ b/core/routers/card/scraper.py @@ -165,6 +165,19 @@ class SiteApi: r = await self.post(url, headers=headers, json=payload) return r + async def cic(self, cert_number: str | int): + """中检检通""" + url = 'https://www.zhongjianjiantong.com/Api/OrderRatingGoods/detail' + payload = { + 'cert_no': cert_number + } + headers = { + 'Content-Type': 'application/json;charset=UTF-8', + 'Referer': "https://www.zhongjianjiantong.com/web/index.html", + } + r = await self.post(url, headers=headers, json=payload) + return r + async def close(self): await self.session.close() @@ -184,6 +197,7 @@ class CardScraper: 'gbtc': self.gbtc, 'ccg': self.ccg, 'bctc': self.bctc, + 'cic': self.cic, } return self._handlers @@ -197,7 +211,8 @@ class CardScraper: info_elements = html.xpath('//div[@hidden and @id]/div[contains(@class, "py-3")]') info = dict() for info_element in info_elements: - name = info_element.xpath('./dt[1]').xpath('string()').get() or info_element.xpath('./dt/template/@id').get() or '' + name = info_element.xpath('./dt[1]').xpath('string()').get() or info_element.xpath( + './dt/template/@id').get() or '' name = re.sub(r'\(|\)', '', name) name = name.lower().replace(' ', '_').replace('/', '_') value = info_element.xpath('./dd[1]').xpath('string()').get() @@ -430,7 +445,43 @@ class CardScraper: return { 'cert_number': item['cert_number'], 'data': item, - 'raw_data': result.get('info'), + 'raw_data': details, + } + + async def cic(self, cert_number: str | int) -> dict | None: + """中检检通""" + r = await self.api.cic(cert_number) + result = r.json() + if result.get('code') != 200: + return + + details = jsonpath(result, '$.data.obj_order_rating_goods', first=True) + + item = dict(cert_number=None) + # 评级卡号 + item['cert_number'] = details.get('cert_no') + # 年份 + item['card_year'] = jsonpath(details, '$.obj_detail.fxnf', first=True) + # 卡片品牌 + item['card_brand'] = jsonpath(details, '$.obj_brand.title', first=True) + # 卡片评分 + item['card_score'] = details.get('score') + # 卡片名称 + item['card_name'] = details.get('goods_name') + # 卡片编号 + item['card_number'] = details.get('tag_no') + # 卡片类型 无 + # 卡片正、反图片(远程) + item['card_spare_picture'] = { + 'front_picture': jsonpath(details, '$.lst_images[0]', first=True), + 'reverse_picture': jsonpath(details, '$.lst_images[1]', first=True) + } + # 来源 + item['source'] = 'cic' + return { + 'cert_number': item['cert_number'], + 'data': item, + 'raw_data': details, } async def choice(self, platform: str, cert_number: str | int) -> dict | None: