为什么用美汤解析网页会得到图片的src属性值为base64字符串?
Why does parsing a webpage with beautiful soup leads to src attributes of images with values as base64 strings?
我正在尝试使用 requests
下载网站的 HTML 代码并使用 beautiful soup
解析它以获取我要下载的一些图像的源代码。
import requests, bs4
res = requests.get('https://www.tutti.ch/de/li/bern?q=gartenstuhl')
soup = bs4.BeautifulSoup(res.text, 'html.parser')
images = soup.select('div[style] > img')
for i in images:
print(i.get('src'))
问题是:我返回数据 URL,这些 URL 似乎对下载图像没有用。
我需要每个 src 属性都是 link,例如 'https://c.tutti.ch/images/4523452354235.jpg'
。如何将 src 属性作为普通 python 字符串数据类型获取?有没有一种简单的方法可以将数据 URL 转换为普通 URL?
我从 Mozilla and GeeksforGeeks 找到了这些资源。我认为这归结为如何解码 base64 字符串的问题。
编辑:新代码片段
res = requests.get('https://www.tutti.ch/de/li/bern?q=gartenstuhl')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, 'html.parser')
#Check for errors from here
images = soup.select('div[style] > img')
for im in images:
imageURL = im.get('src') # get the URL of the image
print('Downloading image %s...' % (imageURL))
res = requests.get(imageURL) # downloads the image
res.raise_for_status()
imageFile = open(os.path.join('tuttiBilder', os.path.basename(imageURL)), 'wb') # creates an image file
for chunk in res.iter_content(100000): # writes to the image file
imageFile.write(chunk)
imageFile.close()
print('Done.')
browser.quit()
您需要用这个 images = soup.find_all('img')
更改第 6 行并将所有这些添加到一个数组中而不是删除 data:image/gif...
import requests
from bs4 import BeautifulSoup
res = requests.get('https://www.tutti.ch/de/li/bern?q=gartenstuhl')
soup = BeautifulSoup(res.text, 'html.parser')
images = soup.find_all('img')
list = [img['src'] for img in images if img.has_attr('src')]
for element in list:
if element[0] == 'd':
list.remove(element)
print(list)
输出:
[
'https://c.tutti.ch/images/2506797800.jpg',
'https://c.tutti.ch/images/2542095444.jpg',
'https://c.tutti.ch/images/2525772665.jpg',
'https://c.tutti.ch/images/2544845483.jpg',
'https://c.tutti.ch/images/0256568721.jpg',
'https://c.tutti.ch/images/2466120894.jpg',
'https://c.tutti.ch/images/5890425922.jpg',
'https://c.tutti.ch/images/6251267695.jpg',
'https://c.tutti.ch/images/6201238303.jpg',
'https://c.tutti.ch/images/2277802675.jpg',
'https://c.tutti.ch/images/2273705997.jpg',
...
]
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
是 one-pixel 由单个黑点组成的图像的 GIF 编码。所以你可能不需要花很多力气来解码它。
数据URLs,将一个HTTP数据object的内容直接编码成一个URL(这样就没有关联文件)有时用来嵌入很小将图像直接放入 HTML 文档中,从而节省了请求和接收小图像的成本。对于小文件,请求和回复 headers 的开销可能远大于文件本身的大小(例如 single-pixel GIF 是 42 字节),因此直接嵌入数据是有意义的,即使考虑到 Base64 编码需要四个字节来编码三个字节的数据这一事实。因此有时能够将数据 URL 转换为文件是很有用的。
数据URL以data:
开头,后跟“媒体类型”、逗号和数据字符串,只能包含URL个字符。媒体类型描述了数据的格式;它由所谓的“mimetype”组成——一对由斜杠分隔的单词,如 image/gif
[注 1]——可能后跟属性列表,每个属性都以分号开头。如果最后一个属性是单词 base64
,则二进制数据已用 Base-64 编码。没有 base64
属性的数据 URLs 与 URLs 一样是“%-encoded”;任何特殊字符都以 %
后跟两个十六进制数字的形式发送。
所以只能处理 GIF 的 simple-minded 解码器可能看起来像:
import base64
import urllib.parse
def dataURI_decode(uri):
if uri.startswith('data:'):
dataFormat, data = uri.split(',', 1)
mimetype, *attrs = dataFormat.split(';')
if attrs and attrs[-1] == 'base64':
return mimetype, base64.b64decode(data)
else:
return mimetype, urllib.parse.unquote_to_bytes(data)
# Sample use to save a GIF from a data url:
uri = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
mimetype, gif = dataURI_decode(uri)
if (mimetype == 'image/gif'):
with open("data.gif", "wb") as f:
f.write(gif)
备注
- 有一个已知 MIME 类型字符串的全局注册表;例如,
image/gif
标识 GIF 文件(或数据流。这些字符串还用于标识通过 HTTP(或 e-mail 消息发送的文件的文件类型)。(您不需要发送文件时必须使用已注册的 mimetype 字符串,但接收文件的浏览器或电子邮件客户端很可能会错误地处理它。)
我正在尝试使用 requests
下载网站的 HTML 代码并使用 beautiful soup
解析它以获取我要下载的一些图像的源代码。
import requests, bs4
res = requests.get('https://www.tutti.ch/de/li/bern?q=gartenstuhl')
soup = bs4.BeautifulSoup(res.text, 'html.parser')
images = soup.select('div[style] > img')
for i in images:
print(i.get('src'))
问题是:我返回数据 URL,这些 URL 似乎对下载图像没有用。
我需要每个 src 属性都是 link,例如 'https://c.tutti.ch/images/4523452354235.jpg'
。如何将 src 属性作为普通 python 字符串数据类型获取?有没有一种简单的方法可以将数据 URL 转换为普通 URL?
我从 Mozilla and GeeksforGeeks 找到了这些资源。我认为这归结为如何解码 base64 字符串的问题。
编辑:新代码片段
res = requests.get('https://www.tutti.ch/de/li/bern?q=gartenstuhl')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, 'html.parser')
#Check for errors from here
images = soup.select('div[style] > img')
for im in images:
imageURL = im.get('src') # get the URL of the image
print('Downloading image %s...' % (imageURL))
res = requests.get(imageURL) # downloads the image
res.raise_for_status()
imageFile = open(os.path.join('tuttiBilder', os.path.basename(imageURL)), 'wb') # creates an image file
for chunk in res.iter_content(100000): # writes to the image file
imageFile.write(chunk)
imageFile.close()
print('Done.')
browser.quit()
您需要用这个 images = soup.find_all('img')
更改第 6 行并将所有这些添加到一个数组中而不是删除 data:image/gif...
import requests
from bs4 import BeautifulSoup
res = requests.get('https://www.tutti.ch/de/li/bern?q=gartenstuhl')
soup = BeautifulSoup(res.text, 'html.parser')
images = soup.find_all('img')
list = [img['src'] for img in images if img.has_attr('src')]
for element in list:
if element[0] == 'd':
list.remove(element)
print(list)
输出:
[
'https://c.tutti.ch/images/2506797800.jpg',
'https://c.tutti.ch/images/2542095444.jpg',
'https://c.tutti.ch/images/2525772665.jpg',
'https://c.tutti.ch/images/2544845483.jpg',
'https://c.tutti.ch/images/0256568721.jpg',
'https://c.tutti.ch/images/2466120894.jpg',
'https://c.tutti.ch/images/5890425922.jpg',
'https://c.tutti.ch/images/6251267695.jpg',
'https://c.tutti.ch/images/6201238303.jpg',
'https://c.tutti.ch/images/2277802675.jpg',
'https://c.tutti.ch/images/2273705997.jpg',
...
]
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
是 one-pixel 由单个黑点组成的图像的 GIF 编码。所以你可能不需要花很多力气来解码它。
数据URLs,将一个HTTP数据object的内容直接编码成一个URL(这样就没有关联文件)有时用来嵌入很小将图像直接放入 HTML 文档中,从而节省了请求和接收小图像的成本。对于小文件,请求和回复 headers 的开销可能远大于文件本身的大小(例如 single-pixel GIF 是 42 字节),因此直接嵌入数据是有意义的,即使考虑到 Base64 编码需要四个字节来编码三个字节的数据这一事实。因此有时能够将数据 URL 转换为文件是很有用的。
数据URL以data:
开头,后跟“媒体类型”、逗号和数据字符串,只能包含URL个字符。媒体类型描述了数据的格式;它由所谓的“mimetype”组成——一对由斜杠分隔的单词,如 image/gif
[注 1]——可能后跟属性列表,每个属性都以分号开头。如果最后一个属性是单词 base64
,则二进制数据已用 Base-64 编码。没有 base64
属性的数据 URLs 与 URLs 一样是“%-encoded”;任何特殊字符都以 %
后跟两个十六进制数字的形式发送。
所以只能处理 GIF 的 simple-minded 解码器可能看起来像:
import base64
import urllib.parse
def dataURI_decode(uri):
if uri.startswith('data:'):
dataFormat, data = uri.split(',', 1)
mimetype, *attrs = dataFormat.split(';')
if attrs and attrs[-1] == 'base64':
return mimetype, base64.b64decode(data)
else:
return mimetype, urllib.parse.unquote_to_bytes(data)
# Sample use to save a GIF from a data url:
uri = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
mimetype, gif = dataURI_decode(uri)
if (mimetype == 'image/gif'):
with open("data.gif", "wb") as f:
f.write(gif)
备注
- 有一个已知 MIME 类型字符串的全局注册表;例如,
image/gif
标识 GIF 文件(或数据流。这些字符串还用于标识通过 HTTP(或 e-mail 消息发送的文件的文件类型)。(您不需要发送文件时必须使用已注册的 mimetype 字符串,但接收文件的浏览器或电子邮件客户端很可能会错误地处理它。)