Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
lmk123568 committed Jul 6, 2024
1 parent f59c5c8 commit fd1989b
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 1 deletion.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
# bilibili_bazaar_tool
b站集市低价搜索工具
基于 streamlit 的 b 站集市低价搜索工具

### 如何使用

下载打包好的 exe 文件,双击运行

> ⚠ 请先登录 bilibili,获取 cookie,就可以利用该 cookie 模拟请求访问集市
### 打包教程

本项目用 pyinstaller 打包

```bash
pyinstaller -F --additional-hooks-dir=./hooks -i "bilibili-line.png" run_main.py
```

打包的关键点在于写好 hook,参考`./hooks/hook-streamlit.py`,将 streamlit 库以及 `main.py``bilibili-line.png` 等文件打包成单个 exe 文件
Binary file added bilibili-line.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions hooks/hook-streamlit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from PyInstaller.utils.hooks import copy_metadata
from PyInstaller.utils.hooks import collect_data_files

datas = [('C:\\Users\\24089\\miniconda3\\envs\\aaa\\Lib\\site-packages\\streamlit\\runtime', './streamlit/runtime')]
datas += copy_metadata("streamlit")
datas += collect_data_files("streamlit")

datas += [(".\\main.py",".")]
datas += [(".\\bilibili-line.png",".")]
178 changes: 178 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import streamlit as st

import time
import pandas as pd
import requests
import json
import os
import sys

def get_path(relative_path):
try:
base_path = sys._MEIPASS
except AttributeError:
base_path = os.path.abspath(".")

return os.path.normpath(os.path.join(base_path, relative_path))

# def fetch_and_show_image(url):
# # 发送HTTP请求下载图片
# response = requests.get(url)
# # 将响应内容转换为BytesIO对象,以便PIL处理
# image_bytes = io.BytesIO(response.content)
# # 使用PIL从BytesIO对象中打开图片
# image = Image.open(image_bytes)
# return image

def get_product(category, price, discount, next_id, cookie):

category = {"手办": 2312, "模型": 2066, "3C": 2273, "周边": 2331}[category]

price = [f"{int(price[0] * 100)}-{int(price[1] * 100)}"]
discount = [f"{int(discount[0] * 10)}-{int(discount[1] * 10)}"]

url = "https://mall.bilibili.com/mall-magic-c/internet/c2c/v2/list"
payload = json.dumps({
"categoryFilter": category,
"nextId": next_id,
"priceFilters": price,
"discountFilters": discount,
})
headers = {
'priority': 'u=1, i',
'Cookie': cookie,
'User-Agent': 'Apifox/1.0.0 (https://apifox.com)',
'content-type': 'application/json'
}

return requests.request("POST", url, headers=headers, data=payload)




if __name__ == "__main__":

# 状态初始化
if "form_submit_button_visible" not in st.session_state:
st.session_state['form_submit_button_visible'] = False

# 主页设置
st.set_page_config(page_title="B 站集市低价搜索", page_icon=get_path("./bilibili-line.png"))

# 侧栏设置
with st.sidebar:
st.header("🎁 B 站集市低价搜索")
st.info("这里是介绍,但不知道写什么")

with st.form(key='my_form'):
# 添加一个按钮到表单

category = st.selectbox(
"种类",
["手办", "模型", "周边", "3C"])


price = st.slider(
"价格",
0.0, 200.0, (25.0, 75.0))

discount = st.slider(
"折扣",
0.0, 10.0, (3.0, 5.0))

cookie = st.text_input("Cookie", placeholder="去集市抓包找 Cookie")
st.write('🔗 [B站集市链接](https://mall.bilibili.com/neul-next/index.html?page=magic-market_index)')

submitted = st.form_submit_button(label='搜索', type="primary", use_container_width=True, disabled=st.session_state['form_submit_button_visible'])


if submitted:
if cookie:
st.session_state['form_submit_button_visible'] = True
with st.status("🌐 爬取集市数据中 ..."):

response_json = st.empty()

next_id = None
result = []

start_time = time.time()

while 1:
response = get_product(category, price, discount, next_id, cookie)
response_json.json(response.json())
# extracted_data = [{key: item[key] for key in ('c2cItemsName', 'showPrice')} for item in response.json()['data']['data']]
# response_json.json(extracted_data)

for i in response.json()['data']['data']:
item_data = {}
item_data['name'] = i['c2cItemsName']
item_data['price'] = float(i['showPrice'])
item_data['market_price'] = float(i['showMarketPrice'])
item_data['discount'] = f"{(item_data['price'] / item_data['market_price'])*10:.1f} 折"
# item_data['img'] = 'https:'+i['detailDtoList'][0]['img']
item_data[
'url'] = "https://mall.bilibili.com/neul-next/index.html?page=magic-market_detail&noTitleBar=1&itemsId=" + str(
i['c2cItemsId']) + "&from=market_index"

result.append(item_data)

if response.json()['data']['nextId'] == None:
break

next_id = response.json()['data']['nextId']

time.sleep(4)

end_time = time.time()

st.success(f"Crawling count: {len(result)}, Crawling time: {(end_time - start_time)/60:.2f} min")

result_df = pd.DataFrame(result)

min_price_df = result_df.groupby('name')['price'].idxmin()
min_price_df = result_df.loc[min_price_df]


min_price_df = pd.merge(min_price_df, result_df['name'].value_counts(), on='name', how='outer')
new_order = ['column1', 'column2', 'column3']
min_price_df = min_price_df.reindex(columns=["name", "count", "price", "market_price", "discount", "url"])
st.dataframe(min_price_df,
column_config={
"name": st.column_config.TextColumn(
label="物品"
),
"count": st.column_config.TextColumn(
label="个数",
width="small",
),
"price": st.column_config.TextColumn(
label="最低价",
width="small",
),
"market_price": st.column_config.TextColumn(
label = "原价",
width = "small",
),
"discount": st.column_config.TextColumn(
label="折扣",
width="small",
),
"url": st.column_config.LinkColumn(
label="链接",
width="small",
display_text="Buy 🛒"
),
},
hide_index=True,
)
st.session_state['form_submit_button_visible'] = False

else:
st.toast("请输入 Cookie", icon="❗")






27 changes: 27 additions & 0 deletions run_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import streamlit

import streamlit.web.cli as stcli
import os, sys


def resolve_path(path):
resolved_path = os.path.abspath(os.path.join(os.getcwd(), path))
return resolved_path

def get_path(relative_path):
try:
base_path = sys._MEIPASS
except AttributeError:
base_path = os.path.abspath(".")

return os.path.normpath(os.path.join(base_path, relative_path))


if __name__ == "__main__":
sys.argv = [
"streamlit",
"run",
get_path("main.py"),
"--global.developmentMode=false",
]
sys.exit(stcli.main())

0 comments on commit fd1989b

Please sign in to comment.