main.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. # -*- coding: utf-8 -*-
  2. import re
  3. import time
  4. import random
  5. from fastapi import FastAPI, HTTPException
  6. import uvicorn
  7. import httpx
  8. from fastapi.responses import HTMLResponse
  9. app = FastAPI()
  10. COIN_ITEMS = {
  11. 'btc': 'https://coinmarketcap.com/currencies/bitcoin/',
  12. 'eth': 'https://coinmarketcap.com/currencies/ethereum/',
  13. 'sol': 'https://coinmarketcap.com/currencies/solana/',
  14. 'sui': 'https://coinmarketcap.com/currencies/sui/',
  15. 'doge': 'https://coinmarketcap.com/currencies/dogecoin/',
  16. 'x': 'https://coinmarketcap.com/currencies/x-empire/',
  17. 'arb': 'https://coinmarketcap.com/currencies/arbitrum/',
  18. 'pepe': 'https://coinmarketcap.com/currencies/pepe/',
  19. 'grass': 'https://coinmarketcap.com/currencies/grass/',
  20. 'bome': 'https://coinmarketcap.com/currencies/book-of-meme/',
  21. }
  22. PROXIES = {
  23. "http://": "http://127.0.0.1:7890",
  24. "https://": "http://127.0.0.1:7890"
  25. }
  26. HEADERS = {
  27. "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"
  28. }
  29. @app.get("/coin/{proxy_type}/{coin_name}", response_class=HTMLResponse)
  30. async def read_coin(coin_name: str, proxy_type: int = 0):
  31. # -------------------------------------------------------------------------------- 所有url --------------------------------------------------------------------------------
  32. if coin_name == 'all':
  33. try:
  34. result = get_all_coin_data(COIN_ITEMS, HEADERS, PROXIES, proxy_type)
  35. # 使用HTMLResponse返回居中的HTML内容
  36. html_result = f"""<html>
  37. <title>all</title>
  38. <body>
  39. <div style="width: 80%; margin: auto; text-align: center; font-size: 18px; padding: 10px;">
  40. {result}
  41. </div>
  42. </body>
  43. </html>"""
  44. return HTMLResponse(content=html_result, status_code=200)
  45. except httpx.RequestError as e:
  46. return HTMLResponse(content=f"<p style='text-align: center;'>Request Error: {e}</p>", status_code=200)
  47. except Exception as e:
  48. return HTMLResponse(content=f"<p style='text-align: center;'>Internal Error: {e}</p>", status_code=200)
  49. else: # -------------------------------------------------------------------------------- 单个url --------------------------------------------------------------------------------
  50. coin_url = COIN_ITEMS.get(coin_name)
  51. if not coin_url:
  52. return HTMLResponse(content=f"<p style='text-align: center;'>error: {coin_name}</p>", status_code=200)
  53. try:
  54. result = get_coin_data(coin_url, HEADERS, PROXIES, proxy_type)
  55. # 使用HTMLResponse返回居中的HTML内容
  56. html_result = f"""<html>
  57. <title>{coin_name}</title>
  58. <body>
  59. <div style="width: 80%; margin: auto; text-align: center; font-size: 18px; padding: 10px;">
  60. {result}
  61. </div>
  62. </body>
  63. </html>"""
  64. return HTMLResponse(content=html_result, status_code=200)
  65. except httpx.RequestError as e:
  66. return HTMLResponse(content=f"<p style='text-align: center;'>Request Error: {e}</p>", status_code=200)
  67. except Exception as e:
  68. return HTMLResponse(content=f"<p style='text-align: center;'>Internal Error: {e}</p>", status_code=200)
  69. def get_coin_data(url: str, headers: dict, proxies: dict, proxy_type: int):
  70. result = ''
  71. if proxy_type:
  72. resp = httpx.get(url=url, headers=headers, proxies=proxies, timeout=3)
  73. else:
  74. resp = httpx.get(url=url, headers=headers, timeout=3)
  75. if resp.status_code != 200:
  76. raise HTTPException(status_code=resp.status_code,detail=f"Failed to retrieve data, status code: {resp.status_code}")
  77. page = resp.text
  78. text = re.search('<strong>(.*?)sc-65e7f566-0', page)
  79. if not text:
  80. return 'No Data'
  81. text = re.sub(r'</strong>', '', text.group(1))
  82. text = re.sub(r'<!-- -->', '', text)
  83. text = re.sub(r'</p></div></div><div class="', '', text)
  84. prices = re.findall(r'\$(\d+\.\d+)', text)
  85. volumes = re.findall(r'\$(\d{1,3}(?:,\d{3})*(?:\.\d+)?)', text)
  86. change = re.findall(r'(up|down) (\d+\.\d+)%', text)
  87. live_market_cap = re.findall(r'\$(\d{1,3}(?:,\d{3})*(?:\.\d+)?)', text)
  88. max_circulating_supply = re.findall(r'(\d{1,3}(?:,\d{3})*)', text)
  89. result += text.replace('我们会实时更新SUI兑换为CNY的价格。 ', '')
  90. if prices:
  91. result += f'\n\nprices: ${prices[0]}'
  92. if volumes:
  93. result += f'\n24-hour trading volume: ${volumes[1]}'
  94. if change:
  95. c = ' '.join(change[0])
  96. result += f'\nchange: {c}%'
  97. if live_market_cap and len(live_market_cap) == 3:
  98. result += f'\nlive market cap: ${live_market_cap[2]}'
  99. if max_circulating_supply:
  100. result += f'\nmax circulating supply: {max_circulating_supply[-1]}'
  101. if result:
  102. result = re.sub(r'price([\S\s]*)?coins\.\n', '', result)
  103. return result.replace('\n', '<br>').replace('. ', '<br>')
  104. def get_all_coin_data(coin_item: str, headers: dict, proxies: dict, proxy_type: int):
  105. result = ''
  106. for c_name, url in coin_item.items():
  107. if proxy_type:
  108. resp = httpx.get(url=url, headers=headers, proxies=proxies, timeout=3)
  109. else:
  110. resp = httpx.get(url=url, headers=headers, timeout=3)
  111. if resp.status_code != 200:
  112. raise HTTPException(status_code=resp.status_code,detail=f"Failed to retrieve data, status code: {resp.status_code}")
  113. page = resp.text
  114. text = re.search('<strong>(.*?)sc-65e7f566-0', page)
  115. if not text:
  116. return 'No Data'
  117. text = re.sub(r'</strong>', '', text.group(1))
  118. text = re.sub(r'<!-- -->', '', text)
  119. text = re.sub(r'</p></div></div><div class="', '', text)
  120. prices = re.findall(r'today is (.*?) USD with', text)
  121. volumes = re.findall(r'trading volume of (.*?) USD', text)
  122. change = re.findall(r'(up|down) (\d+\.\d+)%', text)
  123. live_market_cap = re.findall(r'with a live market cap of (.*?) USD', text)
  124. max_circulating_supply = re.findall(r'max. supply of (.*?) ', text)
  125. result += f'{c_name}\n'
  126. if prices:
  127. result += f'prices: {prices[0]}\n'
  128. if volumes:
  129. result += f'24-hour trading volume: {volumes[0]}\n'
  130. if change:
  131. c = ' '.join(change[0])
  132. result += f'change: {c}%\n'
  133. if live_market_cap and len(live_market_cap) == 3:
  134. result += f'live market cap: {live_market_cap[2]}\n'
  135. if max_circulating_supply:
  136. result += f'max circulating supply: {max_circulating_supply[-1]}\n'
  137. result += '\n'
  138. time.sleep(random.uniform(0.2, 0.5))
  139. return result.replace('\n', '<br>').replace('. ', '<br>')
  140. if __name__ == "__main__":
  141. uvicorn.run("main:app", host="0.0.0.0", port=32900, reload=True)