jack 1 жил өмнө
commit
c7359a5504
4 өөрчлөгдсөн 183 нэмэгдсэн , 0 устгасан
  1. 62 0
      .gitignore
  2. 11 0
      Dockerfile
  3. 10 0
      docker-compose.yaml
  4. 100 0
      main.py

+ 62 - 0
.gitignore

@@ -0,0 +1,62 @@
+.DS_Store
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+.idea/*
+xml_files/
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+

+ 11 - 0
Dockerfile

@@ -0,0 +1,11 @@
+FROM python:3.8
+
+WORKDIR /app
+
+COPY main.py /app
+
+RUN pip install --no-cache-dir fastapi uvicorn httpx
+
+EXPOSE 8000
+
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "32900"]

+ 10 - 0
docker-compose.yaml

@@ -0,0 +1,10 @@
+version: '3.8'
+
+services:
+  coin_api:
+    build: .
+    image: coin_api
+    container_name: coin_api
+    ports:
+      - "32900:32900"
+    restart: always

+ 100 - 0
main.py

@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+import re
+from fastapi import FastAPI, HTTPException
+import uvicorn
+import httpx
+from fastapi.responses import HTMLResponse
+
+app = FastAPI()
+
+COIN_ITEMS = {
+    'btc': 'https://coinmarketcap.com/currencies/bitcoin/',
+    'eth': 'https://coinmarketcap.com/currencies/ethereum/',
+    'sol': 'https://coinmarketcap.com/currencies/solana/',
+    'sui': 'https://coinmarketcap.com/currencies/sui/',
+    'doge': 'https://coinmarketcap.com/currencies/dogecoin/',
+    'x': 'https://coinmarketcap.com/currencies/x-empire/',
+    'arb': 'https://coinmarketcap.com/currencies/arbitrum/',
+    'pepe': 'https://coinmarketcap.com/currencies/pepe/',
+    'grass': 'https://coinmarketcap.com/currencies/grass/',
+    'bome': 'https://coinmarketcap.com/currencies/book-of-meme/',
+}
+
+PROXIES = {
+    "http://": "http://127.0.0.1:7890",
+    "https://": "http://127.0.0.1:7890"
+}
+
+HEADERS = {
+    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107"
+}
+
+
+@app.get("/coin/{proxy_type}/{coin_name}", response_class=HTMLResponse)
+async def read_coin(coin_name: str, proxy_type: int = 0):
+    coin_url = COIN_ITEMS.get(coin_name)
+    if not coin_url:
+        return HTMLResponse(content=f"<p style='text-align: center;'>error: {coin_name}</p>", status_code=200)
+
+    try:
+        result = get_coin_data(coin_url, HEADERS, PROXIES, proxy_type)
+        # 使用HTMLResponse返回居中的HTML内容
+        html_result = f"""<html>
+                            <body>
+                                <div style="width: 80%; margin: auto; text-align: left; font-size: 16px; padding: 20px;">
+                                    {result}
+                                </div>
+                            </body>
+                            </html>"""
+        return HTMLResponse(content=html_result, status_code=200)
+    except httpx.RequestError as e:
+        return HTMLResponse(content=f"<p style='text-align: center;'>Request Error: {e}</p>", status_code=200)
+    except Exception as e:
+        return HTMLResponse(content=f"<p style='text-align: center;'>Internal Error: {e}</p>", status_code=200)
+
+
+def get_coin_data(url: str, headers: dict, proxies: dict, proxy_type: int):
+    result = ''
+    if proxy_type:
+        resp = httpx.get(url=url, headers=headers, proxies=proxies, timeout=3)
+    else:
+        resp = httpx.get(url=url, headers=headers, timeout=3)
+    if resp.status_code != 200:
+        raise HTTPException(status_code=resp.status_code,detail=f"Failed to retrieve data, status code: {resp.status_code}")
+
+    page = resp.text
+    text = re.search('<strong>(.*?)sc-65e7f566-0', page)
+    if not text:
+        return 'No Data'
+
+    text = re.sub(r'</strong>', '', text.group(1))
+    text = re.sub(r'<!-- -->', '', text)
+    text = re.sub(r'</p></div></div><div class="', '', text)
+
+    prices = re.findall(r'\$(\d+\.\d+)', text)
+    volumes = re.findall(r'\$(\d{1,3}(?:,\d{3})*(?:\.\d+)?)', text)
+    change = re.findall(r'(up|down) (\d+\.\d+)%', text)
+    live_market_cap = re.findall(r'\$(\d{1,3}(?:,\d{3})*(?:\.\d+)?)', text)
+    max_circulating_supply = re.findall(r'(\d{1,3}(?:,\d{3})*)', text)
+
+    result += text.replace('我们会实时更新SUI兑换为CNY的价格。 ', '')
+    if prices:
+        result += f'\n\nprices: ${prices[0]}'
+    if volumes:
+        result += f'\n24-hour trading volume: ${volumes[1]}'
+    if change:
+        c = ' '.join(change[0])
+        result += f'\nchange: {c}%'
+    if live_market_cap and len(live_market_cap) == 3:
+        result += f'\nlive market cap: ${live_market_cap[2]}'
+    if max_circulating_supply:
+        result += f'\nmax circulating supply: {max_circulating_supply[-1]}'
+
+    if result:
+        result = re.sub(r'price([\S\s]*)?coins\.\n', '', result)
+
+    return result.replace('\n', '<br>').replace('. ', '<br>')
+
+
+if __name__ == "__main__":
+    uvicorn.run("main:app", host="0.0.0.0", port=32900, reload=True)