Python爬取企业SharePoint站点:认证阶段受阻求助
我懂这种卡认证的挫败感——本来只是想拿个HTML源码,结果卡在最基础的环节,还试了好几种方法都不行,太闹心了。让我们先拆解下你遇到的问题,再试试几个更针对性的方案:
先分析你试过的方法为啥失败
方法一:requests_negotiate_sspi 证书错误
[X509: NO_CERTIFICATE_OR_CRL_FOUND] 这个错误说明你提供的.cer证书格式不对,或者路径有误。如果是SharePoint Online(你的域名是company.sharepoint.com,属于这种),其实根本不需要手动指定证书——微软的证书链是公开可信的,你可以先试试把verify=cert改成verify=False(仅限测试,生产环境别这么干),或者把.cer转换成PEM格式(用openssl x509 -inform der -in certsharepoint.cer -out certsharepoint.pem命令)再试试。
方法二:sharepy 报错 AADSTS90023
这个错误主要是因为你传的是具体页面地址,而sharepy.connect需要的是SharePoint站点的根地址(比如https://company.sharepoint.com),不是带后缀的xxx.aspx页面。另外,现在很多企业用多因素认证(MFA),sharepy对MFA的支持很差,这也是个大坑。
方法三:requests_ntlm 返回登录页面
NTLM认证一般是给本地SharePoint Server用的,而你的是SharePoint Online(基于Azure AD),所以NTLM根本不生效。加上请求头返回200但给登录页面,是因为服务器只是把你导向了Azure AD的登录页,并没有真正完成认证。
针对你的场景(SharePoint Online)的可行方案
方案一:用Microsoft Graph API(官方推荐,最稳定)
SharePoint Online属于Microsoft 365生态,官方推荐用Graph API来访问数据,比直接爬HTML靠谱得多,还能避免各种认证坑。
步骤:
- 先在Azure AD里注册一个应用(个人用的话,注册“仅限个人帐户”的应用就行),获取客户端ID和客户端密钥。
- 用
msal库获取访问令牌,再请求页面内容。
代码示例:
import requests import msal # 替换成你的配置信息 CLIENT_ID = "你的Azure AD应用客户端ID" CLIENT_SECRET = "你的Azure AD应用客户端密钥" TENANT_ID = "你的租户ID(可以是公司域名,比如company.com)" SITE_ROOT_URL = "https://company.sharepoint.com/xxx/xxx/xxx" # 站点根地址,不是具体页面 PAGE_RELATIVE_PATH = "/xxx/xxx.aspx" # 页面相对于站点根的路径 # 获取访问令牌 authority = f"https://login.microsoftonline.com/{TENANT_ID}" scope = ["https://graph.microsoft.com/.default"] app = msal.ConfidentialClientApplication( CLIENT_ID, authority=authority, client_credential=CLIENT_SECRET ) token_result = app.acquire_token_for_client(scopes=scope) if "access_token" in token_result: # 第一步:获取站点ID site_id_response = requests.get( f"https://graph.microsoft.com/v1.0/sites/{SITE_ROOT_URL.replace('https://', '')}", headers={"Authorization": f"Bearer {token_result['access_token']}"} ) site_id = site_id_response.json()["id"] # 第二步:获取页面HTML内容 page_content_response = requests.get( f"https://graph.microsoft.com/v1.0/sites/{site_id}/pages/{PAGE_RELATIVE_PATH.lstrip('/')}/content", headers={"Authorization": f"Bearer {token_result['access_token']}"} ) print(page_content_response.text) else: print(f"获取令牌失败:{token_result.get('error')} - {token_result.get('error_description')}")
方案二:模拟浏览器登录(快速测试用)
如果不想折腾Graph API,用selenium模拟浏览器登录是最直接的——浏览器会自动处理Azure AD的认证流程(包括MFA,需要你手动操作),登录完成后直接拿HTML源码。
代码示例:
from selenium import webdriver from selenium.webdriver.common.by import By import time # 初始化Chrome浏览器(需要提前下载对应版本的ChromeDriver) driver = webdriver.Chrome() driver.get("https://company.sharepoint.com/xxx/xxx/xxx/xxx/xxx.aspx") # 这里可以手动输入用户名、密码,处理MFA;如果是测试环境无MFA,也可以自动填充(不推荐生产用) # 示例自动填充(根据实际页面元素ID调整): # driver.find_element(By.ID, "i0116").send_keys("你的用户名") # driver.find_element(By.ID, "idSIButton9").click() # time.sleep(2) # driver.find_element(By.ID, "i0118").send_keys("你的密码") # driver.find_element(By.ID, "idSIButton9").click() # 等待登录完成(根据实际情况调整等待时间) time.sleep(10) # 获取页面HTML源码 page_html = driver.page_source print(page_html) # 关闭浏览器 driver.quit()
额外注意事项
- 如果你是本地SharePoint Server,可以试试修正后的NTLM认证代码(确保用户名格式是
DOMAIN\\username,更新requests和requests_ntlm到最新版本):
import requests from requests_ntlm import HttpNtlmAuth url = "http://你的本地SharePoint站点地址/xxx/xxx.aspx" username = "你的域\\用户名" password = "你的密码" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', } response = requests.get( url, auth=HttpNtlmAuth(username, password), headers=headers, allow_redirects=True ) if response.status_code == 200: print(response.text) else: print(f"请求失败:状态码 {response.status_code},响应内容 {response.text}")
内容的提问来源于stack exchange,提问作者Sederfo

