Skip to content

Commit

Permalink
更新项目依赖库版本
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeanAmier committed Jun 29, 2024
1 parent e7c4d6d commit b87132e
Show file tree
Hide file tree
Showing 22 changed files with 257 additions and 89 deletions.
16 changes: 16 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM python:3.12.4-slim

LABEL name="XHS-Downloader" version="2.1 Beta" authors="JoeanAmier"

COPY locale /locale
COPY source /source
COPY static /static
COPY LICENSE /LICENSE
COPY main.py /main.py
COPY README.md /README.md
COPY README_EN.md /README_EN.md
COPY requirements.txt /requirements.txt

RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

CMD ["python", "main.py"]
41 changes: 34 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<li>✅ 提取搜索结果作品链接</li>
<li>✅ 提取搜索结果用户链接</li>
</ul>
<p>⭐ XHS-Downloader 开发计划及进度可前往 <a href="https://github.com/users/JoeanAmier/projects/5">Projects</a> 查阅</p>
<h1>📸 程序截图</h1>
<p><b>🎥 点击图片观看演示视频</b></p>
<a href="https://www.bilibili.com/video/BV1PJ4m1Y7Jt/"><img src="static/screenshot/程序运行截图CN1.png" alt=""></a>
Expand Down Expand Up @@ -83,7 +84,8 @@
<p><b>启动:</b>运行命令:<code>python .\main.py server</code></p>
<p><b>关闭:</b>按下 <code>Ctrl</code> + <code>C</code> 关闭服务器</p>
<p><b>请求接口:</b><code>/xhs/</code></p>
<p><b>请求类型:</b><code>POST</code></p>
<p><b>请求方法:</b><code>POST</code></p>
<p><b>请求格式:</b><code>JSON</code></p>
<p><b>请求参数:</b></p>
<table>
<thead>
Expand All @@ -109,8 +111,8 @@
</tr>
<tr>
<td align="center">index</td>
<td align="center">str</td>
<td align="center">下载指定序号的图片文件,仅对图文作品生效;多个序号之间使用空格分隔;<code>download</code> 参数设置为 <code>false</code> 时不生效</td>
<td align="center">list[int]</td>
<td align="center">下载指定序号的图片文件,仅对图文作品生效;<code>download</code> 参数设置为 <code>false</code> 时不生效</td>
<td align="center">null</td>
</tr>
<tr>
Expand All @@ -124,11 +126,17 @@
<p><b>代码示例:</b></p>
<pre>
def api_demo():
server = "http://127.0.0.1:8080"
server = "http://127.0.0.1:8000/xhs/"
data = {
"url": "https://www.xiaohongshu.com/explore/123456789",
"download": True,
"index": [
3,
6,
9,
],
}
response = requests.post(server, data=data)
response = requests.post(server, json=data)
print(response.json())
</pre>
<h1>🕹 用户脚本</h1>
Expand All @@ -152,6 +160,8 @@ async def example():
work_path = "D:\\" # 作品数据/文件保存根路径,默认值:项目根路径
folder_name = "Download" # 作品文件储存文件夹名称(自动创建),默认值:Download
name_format = "作品标题 作品描述"
sec_ch_ua = "" # 请求头 Sec-Ch-Ua
sec_ch_ua_platform = "" # 请求头 Sec-Ch-Ua-Platform
user_agent = "" # User-Agent
cookie = "" # 小红书网页版 Cookie,无需登录,必需参数,登录状态对数据采集有影响
proxy = None # 网络代理
Expand All @@ -166,6 +176,8 @@ async def example():
async with XHS(work_path=work_path,
folder_name=folder_name,
name_format=name_format,
sec_ch_ua=sec_ch_ua,
sec_ch_ua_platform=sec_ch_ua_platform,
user_agent=user_agent,
cookie=cookie,
proxy=proxy,
Expand Down Expand Up @@ -216,10 +228,22 @@ async def example():
<td align="center"><code>发布时间 作者昵称 作品标题</code></td>
</tr>
<tr>
<td align="center">sec_ch_ua</td>
<td align="center">str</td>
<td align="center">浏览器请求头 Sec-Ch-Ua</td>
<td align="center">内置 Chrome Sec-Ch-Ua</td>
</tr>
<tr>
<td align="center">sec_ch_ua_platform</td>
<td align="center">str</td>
<td align="center">浏览器请求头 Sec-Ch-Ua-Platform</td>
<td align="center">内置 Chrome Sec-Ch-Ua-Platform</td>
</tr>
<tr>
<td align="center">user_agent</td>
<td align="center">str</td>
<td align="center">浏览器 User-Agent</td>
<td align="center">内置 chrome user-agent</td>
<td align="center">浏览器 User Agent</td>
<td align="center">内置 Chrome User Agent</td>
</tr>
<tr>
<td align="center">cookie</td>
Expand Down Expand Up @@ -295,6 +319,8 @@ async def example():
</tr>
</tbody>
</table>
<p><b>其他说明:<code>sec_ch_ua</code>、<code>sec_ch_ua_platform</code>、<code>user_agent</code>参数获取示例,仅当程序获取数据失败时需要自行设置!</b></p>
<img src="static/screenshot/请求头示例图.png" alt="">
<h1>🌐 Cookie</h1>
<ol>
<li>打开浏览器(可选无痕模式启动),访问 <code>https://www.xiaohongshu.com/explore</code></li>
Expand Down Expand Up @@ -361,6 +387,7 @@ async def example():

* https://github.com/encode/httpx/
* https://github.com/tiangolo/fastapi
* https://github.com/textualize/textual/
* https://textual.textualize.io/
* https://aiosqlite.omnilib.dev/en/stable/
* https://click.palletsprojects.com/en/8.1.x/
Expand Down
Binary file modified locale/en_GB/LC_MESSAGES/xhs.mo
Binary file not shown.
8 changes: 7 additions & 1 deletion locale/en_GB/LC_MESSAGES/xhs.po
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,13 @@ msgstr "Web API server has been shut down!"
msgid "服务器主机及端口: {0}"
msgstr "Server host and port: {0}"

msgid "内置 Chrome User-Agent"
msgid "内置 Chrome Sec-Ch-Ua"
msgstr "Built in Chrome Sec-Ch-Ua"

msgid "内置 Chrome Sec-Ch-Ua-Platform"
msgstr "Built in Chrome Sec-Ch-Ua-Platform"

msgid "内置 Chrome User Agent"
msgstr "Built in Chrome User Agent"

msgid "proxy 参数 {0} 设置错误,程序将不会使用代理"
Expand Down
8 changes: 7 additions & 1 deletion locale/zh_CN/LC_MESSAGES/xhs.po
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,13 @@ msgstr ""
msgid "服务器主机及端口: {0}"
msgstr ""

msgid "内置 Chrome User-Agent"
msgid "内置 Chrome Sec-Ch-Ua"
msgstr ""

msgid "内置 Chrome Sec-Ch-Ua-Platform"
msgstr ""

msgid "内置 Chrome User Agent"
msgstr ""

msgid "proxy 参数 {0} 设置错误,程序将不会使用代理"
Expand Down
27 changes: 18 additions & 9 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from asyncio import run
from asyncio.exceptions import CancelledError
from contextlib import suppress
from sys import argv

from source import Settings
Expand All @@ -17,6 +19,8 @@ async def example():
work_path = "D:\\" # 作品数据/文件保存根路径,默认值:项目根路径
folder_name = "Download" # 作品文件储存文件夹名称(自动创建),默认值:Download
name_format = "作品标题 作品描述"
sec_ch_ua = "" # 请求头 Sec-Ch-Ua
sec_ch_ua_platform = "" # 请求头 Sec-Ch-Ua-Platform
user_agent = "" # User-Agent
cookie = "" # 小红书网页版 Cookie,无需登录,必需参数,登录状态对数据采集有影响
proxy = None # 网络代理
Expand All @@ -31,6 +35,8 @@ async def example():
async with XHS(work_path=work_path,
folder_name=folder_name,
name_format=name_format,
sec_ch_ua=sec_ch_ua,
sec_ch_ua_platform=sec_ch_ua_platform,
user_agent=user_agent,
cookie=cookie,
proxy=proxy,
Expand All @@ -55,16 +61,19 @@ async def app():
await xhs.run_async()


async def server():
async def server(host="127.0.0.1", port=8000, log_level="info", ):
async with XHS(**Settings().run()) as xhs:
await xhs.run_server()
await xhs.run_server(host, port, log_level, )


if __name__ == '__main__':
if len(argv) == 1:
run(app())
elif argv[1] == "server":
print("该模式重构中!")
# run(server())
else:
cli()
with suppress(
KeyboardInterrupt,
CancelledError,
):
if len(argv) == 1:
run(app())
elif argv[1] == "server":
run(server())
else:
cli()
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
textual>=0.47.1
pyperclip>=1.8.2
lxml>=5.1.0
textual>=0.70.0
pyperclip>=1.9.0
lxml>=5.2.2
PyYAML>=6.0.1
aiosqlite>=0.20.0
click>=8.1.7
browser_cookie3>=0.19.1
httpx>=0.27.0
fastapi>=0.110.0
uvicorn>=0.24.0
fastapi>=0.111.0
uvicorn>=0.30.1
6 changes: 6 additions & 0 deletions source/CLI/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ def help_(ctx: Context, param, value) -> None:
("--work_path", "-wp", "str", _("作品数据 / 文件保存根路径")),
("--folder_name", "-fn", "str", _("作品文件储存文件夹名称")),
("--name_format", "-nf", "str", _("作品文件名称格式")),
("--sec_ch_ua", "-su", "str", _("Sec-Ch-Ua")),
("--sec_ch_ua_platform", "-sp", "str", _("User-Agent")),
("--user_agent", "-ua", "str", _("Sec-Ch-Ua-Platform")),
("--cookie", "-ck", "str", _("小红书网页版 Cookie,无需登录")),
("--proxy", "-p", "str", _("网络代理")),
("--timeout", "-t", "int", _("请求数据超时限制,单位:秒")),
Expand Down Expand Up @@ -163,6 +166,9 @@ def help_(ctx: Context, param, value) -> None:
)
@option("--folder_name", "-fn", )
@option("--name_format", "-nf", )
@option("--sec_ch_ua", "-su", )
@option("--sec_ch_ua_platform", "-sp", )
@option("--user_agent", "-ua", )
@option("--cookie", "-ck", )
@option("--proxy", "-p", )
@option("--timeout", "-t", type=int, )
Expand Down
17 changes: 13 additions & 4 deletions source/TUI/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
class About(Screen):
BINDINGS = [
Binding(
key="q",
key="Q",
action="quit",
description="退出程序/Quit"),
Binding(
key="u",
action="check_update_about",
key="U",
action="check_update",
description="检查更新/Update"),
Binding(
key="b",
key="B",
action="index",
description="返回首页/Back"),
]
Expand All @@ -53,3 +53,12 @@ def compose(self) -> ComposeResult:

def on_mount(self) -> None:
self.title = PROJECT

async def action_quit(self) -> None:
await self.app.action_quit()

async def action_index(self):
await self.app.push_screen("index")

async def action_check_update(self):
await self.app.run_action("update_and_return")
15 changes: 1 addition & 14 deletions source/TUI/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from .about import About
from .index import Index
from .loading import Loading
from .monitor import Monitor
from .record import Record
from .setting import Setting
from .update import Update
Expand Down Expand Up @@ -78,15 +77,6 @@ async def save_settings(data: dict) -> None:

await self.push_screen("setting", save_settings)

async def action_about(self):
await self.push_screen("about")

async def action_index(self):
await self.push_screen("index")

async def action_record(self):
await self.push_screen("record")

async def refresh_screen(self):
self.pop_screen()
await self.close_database()
Expand Down Expand Up @@ -117,13 +107,10 @@ def update_result(self, tip: str) -> None:
async def action_check_update(self):
await self.push_screen(Update(self.APP, self.message), callback=self.update_result)

async def action_check_update_about(self):
async def action_update_and_return(self):
await self.push_screen("index")
await self.action_check_update()

async def action_monitor(self):
await self.push_screen(Monitor(self.APP, self.message))

async def close_database(self):
await self.APP.id_recorder.cursor.close()
await self.APP.id_recorder.database.close()
Expand Down
36 changes: 28 additions & 8 deletions source/TUI/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,19 @@
REPOSITORY,
GENERAL,
)
from .monitor import Monitor

__all__ = ["Index"]


class Index(Screen):
BINDINGS = [
Binding(key="q", action="quit", description="退出程序/Quit"),
Binding(key="u", action="check_update", description="检查更新/Update"),
Binding(key="s", action="settings", description="程序设置/Settings"),
Binding(key="r", action="record", description="下载记录/Record"),
Binding(key="m", action="monitor", description="开启监听/Monitor"),
Binding(key="a", action="about", description="关于项目/About"),
Binding(key="Q", action="quit", description="退出程序/Quit"),
Binding(key="U", action="update", description="检查更新/Update"),
Binding(key="S", action="settings", description="程序设置/Settings"),
Binding(key="R", action="record", description="下载记录/Record"),
Binding(key="M", action="monitor", description="开启监听/Monitor"),
Binding(key="A", action="about", description="关于项目/About"),
]

def __init__(self, app: XHS, message: Callable[[str], str]):
Expand Down Expand Up @@ -73,7 +74,7 @@ def compose(self) -> ComposeResult:
Button(self.message("清空输入框"), id="reset"),
),
)
yield RichLog(markup=True, wrap=True)
yield RichLog(markup=True, )
yield Footer()

def on_mount(self) -> None:
Expand All @@ -86,7 +87,8 @@ def on_mount(self) -> None:
f"\n{
">" *
50}",
style=MASTER), scroll_end=False)
style=MASTER), scroll_end=False,
)
self.xhs.manager.print_proxy_tip(log=self.tip, )

@on(Button.Pressed, "#deal")
Expand Down Expand Up @@ -114,3 +116,21 @@ async def deal(self):
self.tip.write(Text(self.message("下载小红书作品文件失败"), style=ERROR))
self.tip.write(Text(">" * 50, style=GENERAL))
self.app.pop_screen()

async def action_quit(self) -> None:
await self.app.action_quit()

async def action_update(self) -> None:
await self.app.run_action("check_update")

async def action_settings(self):
await self.app.run_action("settings")

async def action_monitor(self):
await self.app.push_screen(Monitor(self.xhs, self.message))

async def action_about(self):
await self.app.push_screen("about")

async def action_record(self):
await self.app.push_screen("record")
Loading

0 comments on commit b87132e

Please sign in to comment.