如何用Python自动下载Qiita中无明确后缀的美国肠道项目数据?
解决Qiita平台美国肠道项目数据自动下载问题
问题原因
直接用requests.get请求下载链接被重定向,是因为Qiita的原始数据下载需要已登录用户的会话认证——网页下载时浏览器会自动携带你登录后的Cookie,而单独的get请求没有携带认证信息,服务器判定未授权,返回官网页面而非数据。
解决方案:用会话维持认证状态
使用requests.Session()维持登录会话,先完成Qiita平台的登录认证,再用同一个会话请求下载链接,同时从响应头提取正确的文件名。
完整代码示例
import requests from requests.exceptions import RequestException # 配置信息 QIITA_LOGIN_URL = "https://qiita.ucsd.edu/auth/login/" DOWNLOAD_URL = "https://qiita.ucsd.edu/download_raw_data/10317" USERNAME = "你的Qiita用户名" PASSWORD = "你的Qiita密码" # 创建会话对象,自动保存Cookie session = requests.Session() # 模拟浏览器请求头,避免被识别为爬虫 session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" }) try: # 第一步:模拟登录Qiita # 获取登录页面的CSRF token(Qiita基于Django,登录需要该参数) login_page = session.get(QIITA_LOGIN_URL) csrf_token = login_page.text.split('name="csrfmiddlewaretoken" value="')[1].split('"')[0] # 构造登录表单数据 login_data = { "username": USERNAME, "password": PASSWORD, "csrfmiddlewaretoken": csrf_token } # 发送登录请求 login_response = session.post(QIITA_LOGIN_URL, data=login_data, allow_redirects=True) # 验证登录是否成功 if "Welcome" not in login_response.text and USERNAME not in login_response.text: raise Exception("登录失败,请检查用户名密码或CSRF token提取逻辑") # 第二步:请求下载链接 download_response = session.get(DOWNLOAD_URL, stream=True) download_response.raise_for_status() # 从响应头提取真实文件名 content_disposition = download_response.headers.get("Content-Disposition") if content_disposition: filename = content_disposition.split('filename="')[1].split('"')[0] else: # fallback到URL最后一段 filename = DOWNLOAD_URL.split("/")[-1] # 分块写入文件,避免大文件占用过多内存 with open(filename, "wb") as f: for chunk in download_response.iter_content(chunk_size=8192): if chunk: f.write(chunk) print(f"文件 {filename} 下载完成") except RequestException as e: print(f"请求出错: {str(e)}") except Exception as e: print(f"处理出错: {str(e)}")
关键细节说明
- 会话维持:
requests.Session()会自动保存登录后的Cookie,后续请求无需重复携带认证信息。 - CSRF Token:Qiita使用Django框架,登录必须携带该参数,需从登录页面的HTML中提取。
- 流式下载:设置
stream=True并分块写入,适合大文件下载,避免内存溢出。 - 文件名提取:优先从
Content-Disposition响应头获取真实文件名,比URL提取更准确。
替代方案(若不想写登录逻辑)
可以手动从浏览器复制已登录的Cookie,直接加入请求头:
import requests DOWNLOAD_URL = "https://qiita.ucsd.edu/download_raw_data/10317" # 从浏览器开发者工具的Cookie中复制sessionid、csrftoken等关键字段 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Cookie": "sessionid=你的sessionid; csrftoken=你的csrftoken" } response = requests.get(DOWNLOAD_URL, headers=headers, stream=True) # 后续文件名提取和写入逻辑同上
注意:Cookie有有效期,过期后需要重新复制。
内容的提问来源于stack exchange,提问作者flotation
相关产品推荐
相关产品推荐

