Python爬虫如何接收过几秒下载的文件

对这块不了解,搜索不出什么东西。标题和内容表达的可能也不太准确,但是目的应该明确的。
是通过 https://www.freemypdf.com/ 上传一些加密但是可以直接查看的 PDF 然后下载解密后的文件
正常操作是上传文件上去后等一会就自动下载。也没有重新加载页面
我理解就是
s = request.Session()
r = s.post(url,data=open(xx,‘rb’))
应该 r.content 就是要下载的文件,但是实际上还是网页。
这应该是保持 HTTP 长连接,然后服务器端推送数据,这样的场景应该不少,请高手指点下,谢谢。
Python爬虫如何接收过几秒下载的文件


14 回复

仔细分析下所有的 HTTP 请求看看


这个问题其实是在问怎么处理爬虫下载文件时的延迟。简单说就是服务器不是立刻返回文件,而是先给个响应说“文件在处理,稍等”,然后过几秒才能真正下载。

核心思路就是轮询或者等待。这里给你两个实用的方法:

方法1:简单等待(适合固定延迟)

import time
import requests

def download_with_delay(url, wait_time=5):
    # 先发送初始请求
    initial_response = requests.get(url)
    
    # 检查响应内容,看是否需要等待
    if "processing" in initial_response.text.lower():
        print(f"文件处理中,等待{wait_time}秒...")
        time.sleep(wait_time)  # 等待指定时间
        
        # 再次请求下载
        final_response = requests.get(url)
        return final_response.content
    else:
        return initial_response.content

# 使用示例
file_content = download_with_delay("http://example.com/generate-report")
with open("report.pdf", "wb") as f:
    f.write(file_content)

方法2:轮询检查(适合不确定延迟)

import requests
import time

def poll_for_download(url, max_attempts=10, interval=3):
    for attempt in range(max_attempts):
        response = requests.get(url)
        
        # 根据响应判断文件是否就绪
        if response.status_code == 200 and len(response.content) > 100:  # 假设文件大于100字节
            return response.content
        elif "ready" in response.text.lower():
            return response.content
        else:
            print(f"第{attempt+1}次检查,文件还未就绪...")
            time.sleep(interval)
    
    raise Exception("文件下载超时")

# 使用
try:
    data = poll_for_download("http://api.example.com/export-data")
    with open("data.zip", "wb") as f:
        f.write(data)
except Exception as e:
    print(f"下载失败: {e}")

关键点:

  • 有些API会返回202 Accepted状态码,表示请求已接受但还在处理
  • 可能需要在响应头中找Retry-After字段,它会告诉你要等多久
  • 对于大文件,考虑用流式下载(stream=True)避免内存问题

简单说就是根据服务器响应决定等多久再重试下载。

requests 上传文件是你这样的?

selenium

Selenium +1

Selenium +2

一般来说,这种后台耗时的任务不会等到任务完成才返回。

后台接收你请求,然后扔到队列排队等待处理,同时返回这个任务的编号,
前端拿到编号去后台轮询,根据轮询结果来判断任务是否完成。

后台处理完成将结果放临时文件,并返回 url,客户端就能拿到结果了。

大概原理就这样,不同网站有不同的处理方法,用浏览器看 network 就够了。

要研究这个过几秒是怎么实现的呀。
一般有两种方式,一种是 html 重定向,这个简单,相信不是难度。
另外一种是通过 js 来触发下载,要么用上面他们说的 Selenium,要么自己分析 js 来组成 url,自己下载。




就一个上传的请求完成后开始下载。network 就只有一条 POST 记录。如果前端轮训的话,应该会产生新的请求。
从浏览器看发送的 Request Header
Content-Length: 735167
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykYxJKfN4BTYmWsR6
接收到的 Response Header
Content-Disposition: attachment; filename=“encrypted [Unlocked by www.freemypdf.com].pdf”;
Content-Length: 733925
Content-Transfer-Encoding: binary
应该接受的到的是文件。
怀疑 POST 有问题,按照浏览器中的改了一下,还是没有成功。继续试验。

那么请问如何上传?

对比一下自己发出去的请求跟正常在页面上发出去的请求之间的区别是可以最有效率地解决此类问题的办法

谢谢。这个思路研究了几天,请求头和请求主体( r.request.header,r.request.body )感觉和网络里看到的基本一致了,但是还是没有下载到文件。还有其他要注意的吗?

贴一下目前尝试的代码

import requests
import os

s = requests.session()
dst_url = ‘https://www.freemypdf.com/#‘

filename = r’.pdf’

headers = {
‘Host’: ‘www.freemypdf.com’,
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0’,
‘Accept’: 'text/html,application/xhtml+xml,application/xml;q=0.9,
/*;q=0.8’,
‘Accept-Language’: ‘zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2’,
‘Accept-Encoding’: ‘gzip, deflate, br’,
‘Referer’: ‘https://www.freemypdf.com/’
}

files = {
‘origpdf’:(os.path.basename(filename), open(filename, ‘rb’), ‘application/pdf’)
}
r = s.post(dst_url,headers = headers,files = files)

#11 不要凭感觉确定,直接在代码里加上使用代理服务器,然后用 Fiddler 之类的先抓一个浏览器上打开的正常请求,再跑一遍代码抓一个你自己发出去的请求,对比一下有问题的地方就很明显了

回到顶部