使用requests/BeautifulSoup爬取HTTPS登录站点PDF损坏及仅下载最后一个文件问题
问题根因
- 最初PDF文件损坏的原因:
- 调用
request.urlretrieve()时传入的是首页地址Sampleurl,而非真实的PDF文件地址,保存的内容本身就不是PDF格式。 urllib的下载请求没有携带requests.session中存储的登录态凭证,网站身份校验失败返回的是错误页面内容,自然无法打开。
- 调整后仅下载最后一个文件的原因:
循环变量定义为for PDF in url_list,但拼接本地文件名时误用了前一段代码残留的url变量,该变量最后一次赋值就是列表最后一个PDF的地址,导致每次循环都使用同一个文件名,前面下载的文件被后续循环覆盖,最终仅保留最后一个文件。
修复后完整代码
# Import libraries import requests from bs4 import BeautifulSoup import os from pprint import pprint import time import re from urllib.parse import urljoin # Fetch username username = os.getlogin() # Set folder location to local users desktop folder_location = r'C:\Users\{0}\desktop\Vodafone_Invoices'.format(username) # 提前创建目标文件夹,避免循环内重复判断 if not os.path.exists(folder_location): os.mkdir(folder_location) Sampleurl = 'https://www.tict.io' loginurl = 'https://www.tict.io/auth/login' secure_url = 'https://www.tict.io/tool/87dd1218-f632-4ddb-b4d2-1f195bb4a5ca' payload = { 'username': 'xxxx', 'password': 'xxx', 'ltfejs': 'xx' } with requests.session() as s: print("Connecting to website") # 校验登录请求是否成功 login_resp = s.post(loginurl, data=payload) if login_resp.status_code not in [200, 302]: print("登录失败,请检查payload参数") exit() r = s.get(secure_url) soup = BeautifulSoup(r.content, 'html.parser') links = soup.find_all('a', href=re.compile(r'(.pdf)')) print("Gathering .PDF files") url_list = [] for el in links: # 用urljoin拼接更稳妥,避免斜杠缺失/重复问题 full_pdf_url = urljoin(Sampleurl, el['href']) url_list.append(full_pdf_url) pprint(url_list) print("Downloading .PDF files") for pdf_url in url_list: # 提取纯文件名 file_name = pdf_url.split("/")[-1] full_file_path = os.path.join(folder_location, file_name) # 已存在的文件跳过下载 if os.path.exists(full_file_path): print(f"{file_name} 已存在,跳过下载") continue # 用已登录的session发起请求,携带登录凭证 pdf_resp = s.get(pdf_url) if pdf_resp.status_code == 200: with open(full_file_path, 'wb') as f: f.write(pdf_resp.content) print(f"{file_name} 下载完成") else: print(f"{file_name} 下载失败,状态码:{pdf_resp.status_code}") print("This program will automatically close in 5 seconds ") time.sleep(5)
优化说明
- 统一使用已登录的session对象发起所有请求,确保PDF下载请求通过网站身份校验
- 提前创建目标文件夹,移除循环内的重复判断逻辑
- 新增本地文件存在校验,已存在的文件自动跳过,符合需求
- 使用
urljoin拼接PDF链接,规避手动字符串拼接可能出现的路径错误 - 新增请求状态码校验,方便定位异常问题
内容的提问来源于stack exchange,提问作者MATH
相关产品推荐
相关产品推荐

