ftjc2021 commited on
Commit
f447a3f
·
verified ·
1 Parent(s): 15edad1

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +22 -0
  2. README.md +29 -11
  3. requirements.txt +2 -0
  4. xhs.py +151 -0
Dockerfile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+
3
+ # 创建非root用户
4
+ RUN useradd -m -u 1000 user
5
+ WORKDIR /app
6
+
7
+ # 复制并安装依赖
8
+ COPY --chown=user ./requirements.txt requirements.txt
9
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
10
+
11
+ # 复制应用文件
12
+ COPY --chown=user . /app
13
+
14
+ # 切换到非root用户
15
+ USER user
16
+
17
+ # 设置环境变量
18
+ ENV HOME=/home/user \
19
+ PATH=/home/user/.local/bin:$PATH
20
+
21
+ # 启动应用(使用端口7860)
22
+ CMD ["python", "xhs.py"]
README.md CHANGED
@@ -1,11 +1,29 @@
1
- ---
2
- title: Xhs
3
- emoji: 🐢
4
- colorFrom: indigo
5
- colorTo: blue
6
- sdk: docker
7
- pinned: false
8
- short_description: xhs
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: 小红书链接转换工具
3
+ emoji: 🔗
4
+ colorFrom: red
5
+ colorTo: pink
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+
11
+ # 小红书链接转换工具
12
+
13
+ 这是一个将小红书分享链接转换为真实可访问链接的API服务。
14
+
15
+ ## API使用说明
16
+
17
+ ### 转换链接
18
+ - **端点:** `/api/convert`
19
+ - **方法:** POST
20
+ - **请求体:**
21
+ ```json
22
+ {
23
+ "text": "包含小红书链接的文本"
24
+ }
25
+ ```
26
+
27
+ ### 健康检查
28
+ - **端点:** `/api/health`
29
+ - **方法:** GET
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ flask==2.0.1
2
+ requests==2.27.1
xhs.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ import re
3
+ import requests
4
+
5
+ app = Flask(__name__)
6
+
7
+ def extract_url(text):
8
+ """从文本中提取小红书链接(短链接或完整链接)"""
9
+ # 匹配形如 http://xhslink.com/xxxx 的短链接
10
+ short_pattern = r'http://xhslink\.com/\S+'
11
+ # 匹配形如 https://www.xiaohongshu.com/discovery/item/xxx 的完整链接
12
+ full_pattern = r'https://www\.xiaohongshu\.com/\S+'
13
+
14
+ # 先尝试匹配短链接
15
+ short_matches = re.findall(short_pattern, text)
16
+ short_urls = [match.rstrip(',').rstrip(',').rstrip('。').rstrip('.') for match in short_matches]
17
+
18
+ # 再尝试匹配完整链接
19
+ full_matches = re.findall(full_pattern, text)
20
+ full_urls = [match.rstrip(',').rstrip(',').rstrip('。').rstrip('.') for match in full_matches]
21
+
22
+ # 返回所有找到的链接及其类型
23
+ result = []
24
+ for url in short_urls:
25
+ result.append(("short", url))
26
+ for url in full_urls:
27
+ result.append(("full", url))
28
+
29
+ return result
30
+
31
+ def get_redirect_url(short_url):
32
+ """获取短链接重定向后的真实链接"""
33
+ try:
34
+ headers = {
35
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
36
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
37
+ "Accept-Language": "en-US,en;q=0.9",
38
+ "Connection": "keep-alive",
39
+ }
40
+ response = requests.get(short_url, headers=headers, allow_redirects=False)
41
+ if response.status_code in [301, 302, 307]:
42
+ return response.headers['Location']
43
+ else:
44
+ return f"错误: 无法获取重定向链接,状态码: {response.status_code}"
45
+ except Exception as e:
46
+ return f"错误: 请求失败 - {str(e)}"
47
+
48
+ def convert_links(text):
49
+ """转换文本中的所有小红书链接"""
50
+ urls = extract_url(text)
51
+ if not urls:
52
+ return {"status": "error", "message": "未找到小红书链接", "results": []}
53
+
54
+ results = []
55
+ for url_type, url in urls:
56
+ if url_type == "short":
57
+ real_url = get_redirect_url(url)
58
+ results.append({
59
+ "type": "short",
60
+ "short_url": url,
61
+ "real_url": real_url
62
+ })
63
+ else: # url_type == "full"
64
+ results.append({
65
+ "type": "full",
66
+ "url": url
67
+ })
68
+
69
+ return {"status": "success", "message": "链接转换成功", "results": results}
70
+
71
+ @app.route('/api/convert', methods=['POST'])
72
+ def api_convert():
73
+ """API端点,接收POST请求并转换链接"""
74
+ if not request.is_json:
75
+ return jsonify({"status": "error", "message": "请求必须是JSON格式"}), 400
76
+
77
+ data = request.get_json()
78
+
79
+ if 'text' not in data:
80
+ return jsonify({"status": "error", "message": "请求中必须包含'text'字段"}), 400
81
+
82
+ text = data['text']
83
+ result = convert_links(text)
84
+
85
+ return jsonify(result)
86
+
87
+ @app.route('/api/health', methods=['GET'])
88
+ def health_check():
89
+ """健康检查端点"""
90
+ return jsonify({"status": "ok", "message": "服务正常运行"})
91
+
92
+ @app.route('/', methods=['GET'])
93
+ def home():
94
+ """主页,显示简单的使用说明"""
95
+ return """
96
+ <html>
97
+ <head>
98
+ <title>小红书链接转换API</title>
99
+ <style>
100
+ body { font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }
101
+ h1 { color: #D81E06; }
102
+ code { background: #f4f4f4; padding: 2px 5px; border-radius: 3px; }
103
+ pre { background: #f4f4f4; padding: 15px; border-radius: 5px; overflow-x: auto; }
104
+ </style>
105
+ </head>
106
+ <body>
107
+ <h1>小红书链接转换API</h1>
108
+ <p>这是一个将小红书分享链接转换为真实可访问链接的API服务。</p>
109
+
110
+ <h2>API使用说明</h2>
111
+ <h3>转换链接</h3>
112
+ <p><strong>端点:</strong> <code>/api/convert</code></p>
113
+ <p><strong>方法:</strong> POST</p>
114
+ <p><strong>请求体:</strong></p>
115
+ <pre>
116
+ {
117
+ "text": "包含小红书链接的文本"
118
+ }
119
+ </pre>
120
+ <p><strong>示例响应:</strong></p>
121
+ <pre>
122
+ {
123
+ "status": "success",
124
+ "message": "链接转换成功",
125
+ "results": [
126
+ {
127
+ "type": "short",
128
+ "short_url": "http://xhslink.com/xxxx",
129
+ "real_url": "https://www.xiaohongshu.com/discovery/item/..."
130
+ }
131
+ ]
132
+ }
133
+ </pre>
134
+
135
+ <h3>健康检查</h3>
136
+ <p><strong>端点:</strong> <code>/api/health</code></p>
137
+ <p><strong>方法:</strong> GET</p>
138
+ <p><strong>示例响应:</strong></p>
139
+ <pre>
140
+ {
141
+ "status": "ok",
142
+ "message": "服务正常运行"
143
+ }
144
+ </pre>
145
+ </body>
146
+ </html>
147
+ """
148
+
149
+ if __name__ == '__main__':
150
+ # 默认运行在7860端口,适配Hugging Face Spaces
151
+ app.run(host='0.0.0.0', port=7860, debug=False)