【问题标题】:How to download an image with Python 3/Selenium if the URL begins with "blob:"?如果 URL 以“blob:”开头,如何使用 Python 3/Selenium 下载图像?
【发布时间】:2018-05-05 13:47:37
【问题描述】:

使用 web.whatsapp.de 时,可以看到接收到的图像的链接可能如下所示:

blob:https://web.whatsapp.com/3565e574-b363-4aca-85cd-2d84aa715c39

如果链接被复制到地址窗口,它将打开图像,但是 - 如果“blob”被忽略 - 它只会打开一个新的 web whatsapp 窗口。

我正在尝试下载此链接显示的图像。

但是使用常见的技术,例如使用 request,或者 urllib.request 甚至 BeautifulSoup 总是会遇到一个问题:url 开头的“blob”会抛出错误。

这些答案Download file from Blob URL with Python 将导致错误

URLError: <urlopen error unknown url type: blob>

或错误

InvalidSchema: No connection adapters were found for 'blob:https://web.whatsapp.com/f50eac63-6a7f-48a4-a2b8-8558a9ffe015'

(使用 BeatufilSoup)

使用原生方法,例如:

import requests

url = 'https://web.whatsapp.com/f50eac63-6a7f-48a4-a2b8-8558a9ffe015'
fileName = 'test.png'
req = requests.get(url)
file = open(fileName, 'wb')
for chunk in req.iter_content(100000):
    file.write(chunk)
file.close()

只会导致与使用 BeautifulSoup 相同的错误。

我在 Python 中使用 Selenium 控制 Chrome,但是我无法使用提供的链接正确下载图像。

【问题讨论】:

  • 能否请您附上您要抓取的 img 的相关 HTML 源代码?
  • web.whatsapp.com ,图像中的 url 链接因用户而异,因此我无法提供示例链接
  • 在该页面上预览共享图像时,下载按钮会出现在角落。您可以尝试在 Selenium 中单击鼠标触发该按钮,这应该会提示浏览器下载 blob 资源。根据我在下面分享的链接,可能需要一些允许自动下载的配置。

标签: javascript python selenium url whatsapp


【解决方案1】:

Blobs 不是通过 URI 远程检索的实际文件。相反,它们是以编程方式生成的伪 URL,映射到二进制数据,以便为浏览器提供参考。 IE。 &lt;img&gt; 没有属性来提供原始数据,因此您改为创建一个 blob 地址来将该数据映射到标准 src 属性。

来自上面链接的 MDN 页面:

从 Blob 读取内容的唯一方法是使用 FileReader。以下代码将 Blob 的内容作为类型化数组读取。

var reader = new FileReader();
reader.addEventListener("loadend", function() {
   // reader.result contains the contents of blob as a typed array
});
reader.readAsArrayBuffer(blob);

【讨论】:

  • 感谢您的洞察力,我对 javascript 还很陌生-您能告诉我作为“blob”我必须适应什么吗? “链接”,我有吗?
  • 如果我输入命令 readAsDataURL("blob:web.whatsapp.com/3565e574-b363-4aca-85cd-2d84aa715c39"),我得到参数不是 blob 类型的错误。示例很棒,但使用时仍然未定义。有没有尝试使用来自 web whatsapp 的示例链接?
  • 它正在寻找一个实际的 Blob 对象而不是一个 URL。据我所知,使用无头浏览器下载文件需要某种类型的解决方法(请参阅:blog.codecentric.de/en/2010/07/…),因为 Javascript(出于安全考虑)不提供自动下载文件的机制。我不清楚是否可以以编程方式下载 blob 资源,因为我还没有遇到过这种无头浏览器使用的任何示例。
【解决方案2】:

blob 是浏览器存储的原始数据的类文件对象。

你可以在chrome://blob-internals/看到他们

可以通过脚本注入使用 Selenium 获取 blob 的内容。但是,您必须通过在创建 blob 的页面/域上运行脚本来遵守跨源策略:

def get_file_content_chrome(driver, uri):
  result = driver.execute_async_script("""
    var uri = arguments[0];
    var callback = arguments[1];
    var toBase64 = function(buffer){for(var r,n=new Uint8Array(buffer),t=n.length,a=new Uint8Array(4*Math.ceil(t/3)),i=new Uint8Array(64),o=0,c=0;64>c;++c)i[c]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(c);for(c=0;t-t%3>c;c+=3,o+=4)r=n[c]<<16|n[c+1]<<8|n[c+2],a[o]=i[r>>18],a[o+1]=i[r>>12&63],a[o+2]=i[r>>6&63],a[o+3]=i[63&r];return t%3===1?(r=n[t-1],a[o]=i[r>>2],a[o+1]=i[r<<4&63],a[o+2]=61,a[o+3]=61):t%3===2&&(r=(n[t-2]<<8)+n[t-1],a[o]=i[r>>10],a[o+1]=i[r>>4&63],a[o+2]=i[r<<2&63],a[o+3]=61),new TextDecoder("ascii").decode(a)};
    var xhr = new XMLHttpRequest();
    xhr.responseType = 'arraybuffer';
    xhr.onload = function(){ callback(toBase64(xhr.response)) };
    xhr.onerror = function(){ callback(xhr.status) };
    xhr.open('GET', uri);
    xhr.send();
    """, uri)
  if type(result) == int :
    raise Exception("Request failed with status %s" % result)
  return base64.b64decode(result)

bytes = get_file_content_chrome(driver, "blob:https://developer.mozilla.org/7f9557f4-d8c8-4353-9752-5a49e85058f5")

【讨论】:

  • 如何将此内容保存到文件或播放音频?
【解决方案3】:

对于在 node 和 selenium 中尝试做同样事情的人,请参考下面。

var script = function (blobUrl) {
    console.log(arguments);
    var uri = arguments[0];
    var callback = arguments[arguments.length - 1];
    var toBase64 = function(buffer) {
        for(var r,n=new Uint8Array(buffer),t=n.length,a=new Uint8Array(4*Math.ceil(t/3)),i=new Uint8Array(64),o=0,c=0;64>c;++c)
            i[c]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charCodeAt(c);for(c=0;t-t%3>c;c+=3,o+=4)r=n[c]<<16|n[c+1]<<8|n[c+2],a[o]=i[r>>18],a[o+1]=i[r>>12&63],a[o+2]=i[r>>6&63],a[o+3]=i[63&r];return t%3===1?(r=n[t-1],a[o]=i[r>>2],a[o+1]=i[r<<4&63],a[o+2]=61,a[o+3]=61):t%3===2&&(r=(n[t-2]<<8)+n[t-1],a[o]=i[r>>10],a[o+1]=i[r>>4&63],a[o+2]=i[r<<2&63],a[o+3]=61),new TextDecoder("ascii").decode(a)
    };
    var xhr = new XMLHttpRequest();
    xhr.responseType = 'arraybuffer';
    xhr.onload = function(){ callback(toBase64(xhr.response)) };
    xhr.onerror = function(){ callback(xhr.status) };
    xhr.open('GET', uri);
    xhr.send();
}
driver.executeAsyncScript(script, imgEleSrc).then((result) => {
    console.log(result);
})

详细解释请参考以下链接 https://medium.com/@anoop.goudar/how-to-get-data-from-blob-url-to-node-js-server-using-selenium-88b1ad57e36d

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-11
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多