V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
bmos
V2EX  ›  Python

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

  •  
  •   bmos · 2018-11-02 15:08:12 +08:00 · 2520 次点击
    这是一个创建于 2238 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对这块不了解,搜索不出什么东西。标题和内容表达的可能也不太准确,但是目的应该明确的。
    是通过 https://www.freemypdf.com/ 上传一些加密但是可以直接查看的 PDF 然后下载解密后的文件
    正常操作是上传文件上去后等一会就自动下载。也没有重新加载页面
    我理解就是
    s = request.Session()
    r = s.post(url,data=open(xx,'rb'))
    应该 r.content 就是要下载的文件,但是实际上还是网页。
    这应该是保持 HTTP 长连接,然后服务器端推送数据,这样的场景应该不少,请高手指点下,谢谢。
    13 条回复    2018-11-08 16:39:29 +08:00
    misaka19000
        1
    misaka19000  
       2018-11-02 15:20:40 +08:00
    仔细分析下所有的 HTTP 请求看看
    woshilibai
        2
    woshilibai  
       2018-11-02 16:27:50 +08:00 via Android
    requests 上传文件是你这样的?
    shawndev
        3
    shawndev  
       2018-11-02 16:33:53 +08:00
    selenium
    Daveedo
        4
    Daveedo  
       2018-11-02 16:35:09 +08:00
    Selenium +1
    CoderEQ
        5
    CoderEQ  
       2018-11-02 16:36:44 +08:00
    Selenium +2
    lc1450
        6
    lc1450  
       2018-11-02 16:40:33 +08:00
    一般来说,这种后台耗时的任务不会等到任务完成才返回。

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

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

    大概原理就这样,不同网站有不同的处理方法,用浏览器看 network 就够了。
    forgottencoast
        7
    forgottencoast  
       2018-11-02 21:55:55 +08:00
    要研究这个过几秒是怎么实现的呀。
    一般有两种方式,一种是 html 重定向,这个简单,相信不是难度。
    另外一种是通过 js 来触发下载,要么用上面他们说的 Selenium,要么自己分析 js 来组成 url,自己下载。
    bmos
        8
    bmos  
    OP
       2018-11-05 10:48:36 +08:00
    @misaka19000
    @lc1450
    @forgottencoast
    就一个上传的请求完成后开始下载。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 有问题,按照浏览器中的改了一下,还是没有成功。继续试验。
    bmos
        9
    bmos  
    OP
       2018-11-05 10:53:19 +08:00
    @woshilibai 那么请问如何上传?
    locoz
        10
    locoz  
       2018-11-08 13:17:18 +08:00
    对比一下自己发出去的请求跟正常在页面上发出去的请求之间的区别是可以最有效率地解决此类问题的办法
    bmos
        11
    bmos  
    OP
       2018-11-08 14:50:46 +08:00
    @locoz 谢谢。这个思路研究了几天,请求头和请求主体( r.request.header,r.request.body )感觉和网络里看到的基本一致了,但是还是没有下载到文件。还有其他要注意的吗?
    bmos
        12
    bmos  
    OP
       2018-11-08 15:33:14 +08:00
    贴一下目前尝试的代码

    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)
    locoz
        13
    locoz  
       2018-11-08 16:39:29 +08:00
    @bmos #11 不要凭感觉确定,直接在代码里加上使用代理服务器,然后用 Fiddler 之类的先抓一个浏览器上打开的正常请求,再跑一遍代码抓一个你自己发出去的请求,对比一下有问题的地方就很明显了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1013 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:23 · PVG 05:23 · LAX 13:23 · JFK 16:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.