接入 Claude2 API 的完整 Python 客户端指南
目录
想使用Claude 2.0 API 需要排队申请,非常难申请.我们可以能通过python模仿网页端请求了,加上多账号可以无限制使用
1.前期准备
- 梯子
- python3.9环境
- claude账号 (没有可以到某宝购买)
2.安装依赖
pip install requests curl_cffi python-dotenv PyPDF2
3.python 代码
import json
import os
import uuid
import requests
from curl_cffi import requests, Curl, CurlOpt, CurlError
from dotenv import load_dotenv
from common.log import logger
import PyPDF2
# import docx
import re
from io import BytesIO
load_dotenv() # Load environment variables from .env file
class Client:
def __init__(self, cookie, use_proxy=False):
self.cookie = cookie
self.use_proxy = use_proxy
self.proxies = self.load_proxies_from_env()
# logger.info("__init__: use_proxy: {}".format(self.use_proxy))
# logger.info("__init__: proxies: {}".format(self.proxies))
self.organization_id = self.get_organization_id()
# self.organization_id ="28912dc3-bcd3-43c5-944c-a943a02d19fc"
def load_proxies_from_env(self):
proxies = {}
if self.use_proxy:
http_proxy = os.getenv('HTTP_PROXY')
https_proxy = os.getenv('HTTPS_PROXY')
socks5_proxy = os.getenv('SOCKS5_PROXY')
if http_proxy:
proxies['http'] = http_proxy
if https_proxy:
proxies['https'] = https_proxy
if socks5_proxy:
proxies['https'] = socks5_proxy
return proxies
def get_organization_id(self):
url = "https://claude.ai/api/organizations"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.125 Safari/537.36',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}'
}
response = self.send_request("GET", url, headers=headers)
if response.status_code == 200:
res = json.loads(response.text)
uuid = res[0]['uuid']
return uuid
else:
print(f"Error: {response.status_code} - {response.text}")
def get_content_type(self, file_path):
# Function to determine content type based on file extension
extension = os.path.splitext(file_path)[-1].lower()
if extension == '.pdf':
return 'application/pdf'
elif extension == '.txt':
return 'text/plain'
elif extension == '.csv':
return 'text/csv'
# Add more content types as needed for other file types
else:
return 'application/octet-stream'
# Lists all the conversations you had with Claude
def list_all_conversations(self):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}'
}
response = self.send_request("GET", url, headers=headers)
conversations = response.json()
# Returns all conversation information in a list
if response.status_code == 200:
return conversations
else:
print(f"Error: {response.status_code} - {response.text}")
# Send Message to Claude
def send_message(self, prompt, conversation_id, attachment=None):
url = "https://claude.ai/api/append_message"
# print("send_message,attachment"+attachment)
# Upload attachment if provided
attachments = []
if attachment:
attachment_response = self.upload_attachment(attachment)
if attachment_response:
attachments = [attachment_response]
else:
return {"Error: Invalid file format. Please try again."}
# Ensure attachments is an empty list when no attachment is provided
if not attachment:
attachments = []
payload = json.dumps({
"completion": {
"prompt": f"{prompt}",
"timezone": "Asia/Kolkata",
"model": "claude-2"
},
"organization_uuid": f"{self.organization_id}",
"conversation_uuid": f"{conversation_id}",
"text": f"{prompt}",
"attachments": attachments
})
# headers = {
# 'User-Agent':
# 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
# 'Accept': 'text/event-stream, text/event-stream',
# 'Accept-Language': 'en-US,en;q=0.5',
# 'Referer': 'https://claude.ai/chats',
# 'Content-Type': 'application/json',
# 'Origin': 'https://claude.ai',
# 'DNT': '1',
# 'Connection': 'keep-alive',
# 'Cookie': f'{self.cookie}',
# 'Sec-Fetch-Dest': 'empty',
# 'Sec-Fetch-Mode': 'cors',
# 'Sec-Fetch-Site': 'same-origin',
# 'TE': 'trailers'
# }
headers = [
b'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
b'Accept: text/event-stream, text/event-stream',
b'Accept-Language: en-US,en;q=0.5',
b'Referer: https://claude.ai/chats',
b'Content-Type: application/json',
b'Origin: https://claude.ai',
b'DNT: "1"',
b'Connection: keep-alive',
b'Cookie: '+self.cookie.encode("utf-8"),
b'Sec-Fetch-Dest: empty',
b'Sec-Fetch-Mode: cors',
b'Sec-Fetch-Site: same-origin',
b'TE: trailers'
]
# response = self.send_request("POST",url,headers=headers, data=payload, stream=True)
# decoded_data = response.content.decode("utf-8")
# #logger.info("send_message {} decoded_data:".format(decoded_data))
# decoded_data = re.sub('\n+', '\n', decoded_data).strip()
# data_strings = decoded_data.split('\n')
# completions = []
# for data_string in data_strings:
# json_str = data_string[6:].strip()
# data = json.loads(json_str)
# if 'completion' in data:
# completions.append(data['completion'])
#
# answer = ''.join(completions)
# logger.info("send_message {} answer:".format(answer))
buffer = BytesIO()
c = Curl()
def stream_callback(data):
json_str = data.decode('utf-8')
decoded_data = re.sub('\n+', '\n', json_str).strip()
data_strings = decoded_data.split('\n')
for data_string in data_strings:
json_str = data_string[6:].strip()
_data = json.loads(json_str)
if 'completion' in _data:
buffer.write(str(_data['completion']).encode('utf-8'))
print(_data['completion'], end="")
c.setopt(CurlOpt.URL, b'https://claude.ai/api/append_message')
c.setopt(CurlOpt.WRITEFUNCTION, stream_callback)
c.setopt(CurlOpt.HTTPHEADER, headers)
c.setopt(CurlOpt.POSTFIELDS, payload)
c.impersonate("chrome110")
try:
c.perform()
except CurlError as e:
print(f"请求失败: {e}")
# c.perform()
c.close()
body = buffer.getvalue()
print(body.decode())
return body
# Deletes the conversation
def delete_conversation(self, conversation_id):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations/{conversation_id}"
payload = json.dumps(f"{conversation_id}")
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/json',
'Content-Length': '38',
'Referer': 'https://claude.ai/chats',
'Origin': 'https://claude.ai',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'TE': 'trailers'
}
response = self.send_request(
"DELETE", url, headers=headers, data=payload)
# Returns True if deleted or False if any error in deleting
if response.status_code == 200:
return True
else:
return False
# Returns all the messages in conversation
def chat_conversation_history(self, conversation_id):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations/{conversation_id}"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}'
}
response = self.send_request(
"GET", url, headers=headers, params={'encoding': 'utf-8'})
print(type(response))
# List all the conversations in JSON
return response.json()
def generate_uuid(self):
random_uuid = uuid.uuid4()
random_uuid_str = str(random_uuid)
formatted_uuid = f"{random_uuid_str[0:8]}-{random_uuid_str[9:13]}-{random_uuid_str[14:18]}-{random_uuid_str[19:23]}-{random_uuid_str[24:]}"
return formatted_uuid
def create_new_chat(self):
url = f"https://claude.ai/api/organizations/{self.organization_id}/chat_conversations"
uuid = self.generate_uuid()
payload = json.dumps({"uuid": uuid, "name": ""})
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Content-Type': 'application/json',
'Origin': 'https://claude.ai',
'DNT': '1',
'Connection': 'keep-alive',
'Cookie': self.cookie,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'TE': 'trailers'
}
response = self.send_request(
"POST", url, headers=headers, data=payload)
# Returns JSON of the newly created conversation information
return response.json()
# Resets all the conversations
def reset_all(self):
conversations = self.list_all_conversations()
for conversation in conversations:
conversation_id = conversation['uuid']
delete_id = self.delete_conversation(conversation_id)
return True
def upload_attachment(self, file_path):
# '.docx',
if file_path.endswith(('.txt', '.pdf', '.csv', '.doc')):
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
file_type = "text/plain"
file_content = ""
if file_path.endswith('.txt'):
with open(file_path, 'r', encoding='utf-8') as file:
file_content = file.read()
elif file_path.endswith('.pdf'):
with open(file_path, 'rb') as file:
pdf_reader = PyPDF2.PdfFileReader(file)
for page_num in range(pdf_reader.numPages):
page = pdf_reader.getPage(page_num)
file_content += page.extractText()
# elif file_path.endswith(('.doc', '.docx')):
# doc = docx.Document(file_path)
# paragraphs = doc.paragraphs
# for paragraph in paragraphs:
# file_content += paragraph.text
return {
"file_name": file_name,
"file_type": file_type,
"file_size": file_size,
"extracted_content": file_content
}
url = 'https://claude.ai/api/convert_document'
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Referer': 'https://claude.ai/chats',
'Origin': 'https://claude.ai',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'TE': 'trailers'
}
file_name = os.path.basename(file_path)
content_type = self.get_content_type(file_path)
files = {
'file': (file_name, open(file_path, 'rb'), content_type),
'orgUuid': (None, self.organization_id)
}
response = self.send_request(url, "POST", headers=headers, files=files)
if response.status_code == 200:
return response.json()
else:
return False
# Renames the chat conversation title
def rename_chat(self, title, conversation_id):
url = "https://claude.ai/api/rename_chat"
payload = json.dumps({
"organization_uuid": f"{self.organization_id}",
"conversation_uuid": f"{conversation_id}",
"title": f"{title}"
})
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/json',
'Referer': 'https://claude.ai/chats',
'Origin': 'https://claude.ai',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Connection': 'keep-alive',
'Cookie': f'{self.cookie}',
'TE': 'trailers'
}
response = self.send_request(
"POST", url, headers=headers, data=payload)
if response.status_code == 200:
return True
else:
return False
def send_request(self, method, url, headers, data=None, files=None, params=None, stream=False):
if self.use_proxy:
return requests.request(method, url, headers=headers, data=data, files=files, params=params, impersonate="chrome110", proxies=self.proxies, timeout=500)
else:
return requests.request(method, url, headers=headers, data=data, files=files, params=params, impersonate="chrome110", timeout=500)
4.使用
https://claude.ai/ 登陆进去之后按下 F12 在 Cookie 里找到你的 sessionKye 把值复制出来 也可以通过
https://claude.ai/chat/xxx-xx-xxx-xx-xxx
F12 带xxx-xx-xxx-xx-xxx名称的请求参数 cookie 获取 注意接口请求有限制,可注册多账号轮流使用
from claude_api import Client
from curl_cffi import requests, Curl, CurlOpt
cookie = "xxxxx"
claude_api = Client(cookie)
# conversations = claude_api.list_all_conversations()
# for conversation in conversations:
# conversation_id = conversation['uuid']
# print(conversation_id)
# prompt = """
# 根据下文帮我抽取所有人物,及人物特征:
# 这一章主要描述了萧宁和萧薰儿两人在萧家斗技堂的比试。
# 萧宁是萧家大长老的孙子,已修炼到八段斗之气,在萧家年轻一代中实力很强。
# 萧薰儿是萧家九段斗之气的高手,是萧家年轻一代中的第一人。
# 两人比试时,萧宁全力出手,但萧薰儿轻松化解了他的攻击,一掌将萧宁击败。
# 比试结束后,萧宁表现出对萧薰儿的爱慕之情,但萧薰儿态度很生疏。
# 随后萧薰儿去找站在一旁看比试的萧炎说话,萧炎是萧家另一位年轻人。
# 文中还提到萧炎和萧宁关系不太亲密,两人只是有些生疏的打招呼。
# 从人物关系和事件过程来看,主要描述了萧家三位年轻人之间比较复杂的关系。"""
prompt = "根据下文帮我抽取所有人物,及人物特征。内容如下: 姜峰是神桥境界的强者,但是因为神力源泉枯竭而无法施展神通。叶凡出手将姜峰打飞出去,脸上留下印记。这让姜峰感到极度羞辱。他愤怒地想报复叶凡,但叶凡的体魄更强,直接将姜峰打跪在地。叶凡继续羞辱姜峰,称他高高在上目中无人,最后扭断了姜峰的脖子,为两年前的仇报了回去。这场景吸引了周围所有人的注意,他们看到一个凡人的叶凡居然能打败神桥境界的强者,感到震惊。叶凡继续杀死其他想阻止他的人。姜家的长老姜汉忠出手相救,和叶凡发生了激烈交战。三大家族的长老都意识到叶凡服用了圣药,拥有异于常人的强大力量。他们想留下叶凡,让叶凡去神山上采摘神药。叶凡明白他们的意图,表面上同意,心里却暗自盘算要利用他们,再想办法逃脱。"
conversation_id = claude_api.create_new_chat()['uuid']
# print("新窗口ID:"+conversation_id)
# prompt = "举个例子"
response = claude_api.send_message(
prompt, conversation_id)
print(response)