Python 通过URL生成报告并获取请求

Python 通过URL生成报告并获取请求,python,soap,python-requests,salesforce,Python,Soap,Python Requests,Salesforce,通过浏览器使用get请求,我可以从Salesforce以.csv格式下载报告 但是,当我尝试使用Python和requests模块复制此操作时,我无法将报告生成为.csv或数据帧 请求遵循以下模式: url = '{0}/{1}?export=1&enc=ISO-8859-1&xf=csv&isdtp=nv'.format(base_url, report_id) 我已认证如下: import requests import logging # Function to

通过浏览器使用get请求,我可以从Salesforce以.csv格式下载报告

但是,当我尝试使用Python和requests模块复制此操作时,我无法将报告生成为.csv或数据帧

请求遵循以下模式:

url = '{0}/{1}?export=1&enc=ISO-8859-1&xf=csv&isdtp=nv'.format(base_url, report_id)
我已认证如下:

import requests
import logging
# Function to establish a connection to Salesforce: sforce_connect => function() 
def sforce_connect(c_id, cs_id, sforce_uname, sforce_pwd):
    """Function to create a connection with Salesforce.
        Dependent on the requests module.
    Args:
        c_id (str): A string scalar denoting the Consumer (Client) ID.
        cs_id (str): A string scalar denoting the Consumer (Client) Secret ID
        sforce_uname (str): A string scalar denoting the user's salesforce username.
        sforce_pwd (str): A string scalar denoting the user's salesforce password.
    Returns:
        (list): A list comprised of the instance_url (str) scalar, and the oauth details (dict).
    """
    # Store the auth url as a string scalar: auth_url => string scalar
    # Visit https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_oauth_endpoints.htm
    auth_url = 'https://login.salesforce.com/services/oauth2/token'    
    # Callback URL: redirect_url => string scalar
    # redirect_uri = 'http://localhost/'
    # Defensively attempt to:
    try:
        # Issue a POST request in order to retrieve access token: response => response object
        response = requests.post(auth_url, data = {
                            'client_id': c_id,
                            'client_secret': cs_id,
                            'grant_type': 'password',
                            'username': sforce_uname,
                            'password': sforce_pwd})
    # If an error occurs:
    except Exception as error:
        # Log the error: str => stdout(logfile)
        logging.critical("Failed to retrieve Bearer token from Salesforce API, rest of run will be problematic, the "
                         + " error caught: " + repr(error))
    # Extract the json from the response: json_res => json object
    json_res = response.json()
    # Extract the access token from the json response object: access_token => string scalar
    access_token = json_res['access_token']
    # Extract the token type from the json response object: token_type => string scalar
    token_type = json_res['token_type']
    # Extract the session id: session_id => string scalar
    session_id = json_res['id']
    # A dictionary denoting the Authorisation string required, token type concatenated with the token: auth => dictionary
    oauth = {'Authorization': ' '.join([token_type, access_token])}
    # Extract the instance url from the response.json(): instance_url => string scalar 
    instance_url = json_res['instance_url']
    # Explicitly define the return object: list => GlobalEnv() 
    return([instance_url, oauth, session_id])

# Apply the function to establish a connection with salesforce: 
# instance_url => string scalar, auth => dictionary, session_id => string scalar
instance_url, auth, session_id = sforce_connect(
    client_id, client_secret, sfdc_user, sfdc_pass
)
我尝试按如下方式检索.csv,但它没有生成:

req = requests.get(url, headers = auth)
df = pd.read_csv(req.content) 
出于安全考虑,我不能使用simple salesforce软件包或Selenium(并且仅限于请求,urllib3)。任何帮助都将不胜感激

此外,这是返回的对象:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">





<script>
function redirectOnLoad() {
var escapedHash = '';
var url = '/saml/authn-request.jsp?saml_request_id=PERSONAL INFO;
if (window.location.hash) {
   escapedHash = '%23' + window.location.hash.slice(1);
}
if (window.location.replace){ 
window.location.replace(url + escapedHash);
} else {
window.location.href = url + escapedHash;
} 
} 
redirectOnLoad();
</script>

</head>


</html>





<!-- Body events -->
<script type="text/javascript">function bodyOnLoad(){if(window.PreferenceBits){window.PreferenceBits.prototype.csrfToken="null";};}function bodyOnBeforeUnload(){}function bodyOnFocus(){}function bodyOnUnload(){}</script>
            
</body>
</html>


<!--
...................................................................................................
...................................................................................................
...................................................................................................
...................................................................................................
-->

函数redirectOnLoad(){
var escapedHash='';
var url='/saml/authn request.jsp?saml_request_id=个人信息;
if(window.location.hash){
escapedHash='%23'+window.location.hash.slice(1);
}
if(window.location.replace){
window.location.replace(url+escapedHash);
}否则{
window.location.href=url+escapedHash;
} 
} 
重定向加载();
函数bodyOnLoad(){if(window.PreferenceBits){window.PreferenceBits.prototype.csrfToken=“null”;};}函数bodyOnBeforeUnload(){}函数bodyOnFocus(){}函数bodyOnOnLoad(){}

您需要传递HTTP头
Cookie sid={access\u token}
。这是黑客,不是官方支持的API yadda yadda,可以随时破解。你已经被警告过了

看看这些

  • (Python示例)
  • (不是Python,但我添加了原始请求和响应的屏幕截图)
  • (阅读答案、评论,并投票表决一个更正式的方法)
  • 编辑

    好吧,这是OAuth2的错;)我做了一点实验

    如果您进行了正确的OAuth2登录调用,您将获得一个受限会话\u id/access\u令牌。它没有下载报告的权限,即使在作用域中允许使用“已连接的应用程序”
    web
    。要正确模拟人工和浏览器流量,您需要老式的SOAP调用

    你将看到的是一堆热气腾腾的。。。没有错误处理,可能没有遵循Python最佳实践,使用正则表达式()解析XML。。。检查它,但尝试从simple salesforce的源代码中提取更多生产就绪代码,即使您实际上无法在项目中使用它

    import requests
    import re
    
    auth_url="https://test.salesforce.com/services/Soap/u/51.0"
    headers = {'Content-Type': 'text/xml;charset=UTF-8', 'SOAPAction' : "login"}
    body = """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
       <soapenv:Body>
          <urn:login>
             <urn:username>username goes here</urn:username>
             <urn:password>password and optionally security token</urn:password>
          </urn:login>
       </soapenv:Body>
    </soapenv:Envelope>"""
    
    login_response = requests.post(auth_url,data=body,headers=headers)
    print(login_response.content)
    session_id = re.search('<sessionId>(.*)</sessionId>', login_response.content.decode('utf-8')).group(1)
    print(session_id)
    
    report_url = 'https://your instance.my.salesforce.com/reportgoeshere?isdtp=p1&export=1&enc=UTF-8&xf=csv'
    
    reportReq = requests.get(report_url, cookies={'sid': session_id})
    reportData = reportReq.content.decode('utf-8')
    print(reportData)
    
    导入请求
    进口稀土
    验证url=”https://test.salesforce.com/services/Soap/u/51.0"
    headers={'Content-Type':'text/xml;charset=UTF-8','SOAPAction':“login”}
    body=”“”
    用户名在这里
    密码和可选的安全令牌
    """
    login\u response=requests.post(auth\u url,data=body,headers=headers)
    打印(登录\响应.内容)
    session_id=re.search('(.*),login_response.content.decode('utf-8')).group(1)
    打印(会话id)
    报告https://your instance.my.salesforce.com/reportgoesher?isdtp=p1&export=1&enc=UTF-8&xf=csv'
    reportReq=requests.get(report\u url,cookies={'sid':session\u id})
    reportData=reportReq.content.decode('utf-8')
    打印(报表数据)
    
    非常感谢您的回复(+1)。我已经看过你以前的帖子了。但是,我无法将响应对象设置为报表本身,随后也无法将报表设置为数据帧。不幸的是,它返回一些自动生成的javascript。我将修改我的帖子以显示我收到的输出。另外,提供给
    cookies
    参数的参数是否不是
    {'sid':'session\u id'}
    ?即get请求现在是:
    s=requests.get(url,headers=oauth,cookies={'sid':session\u id})
    现在就试试看,但如果可以的话——让这篇文章更具python风格,并将其作为您自己的答案发布,我不希望人们盲目地将其复制到他们的项目中……非常感谢您的所有帮助,不幸的是,我似乎仍然无法获得数据。从你的发帖请求中,我得到一个500错误。