常见的网页请求方式主要有两种:GET(请求内容),POST(发送内容)。一般我们爬虫爬取网页大多使用 GET 请求。
在 python 中我们使用 requests 这个模块来模拟网页发送请求:
x# 导入 requests 用于发送网页请求
import requests
# 要爬取的网页
url = "http://ky0ha.com/creating_page.html"
# 使用 requests 发送 get 请求,请求目标是 url 变量内字符串对应的网页
response = requests.get(url=url)
对网页发送的请求叫 requests,从网页得到的响应叫 response。上面的代码我们发送了 get 请求,并将变量放在 response 里面。我们来打印一下 response 看一下里面的内容是什么。
xxxxxxxxxx
print(response)
查看输出的结果:
xxxxxxxxxx
<Response [200]>
我们会发现输出的内容里面有 200
字样,这个数字描述对本次的响应代码。响应代码分为五类,分别以开头的数字来分,分为 1、2、3、4、5 类。
1xx 表示请求未完成,表示请求正在进行。这种响应只是一个临时的响应。
2xx 表示请求成功,常见的状态码有下面几种:
200:请求成功
201:请求创建资源成功
203:请求的内容成功响应,但是响应的内容并不来自于目标服务器
204:请求成功,但是不返回任何内容
206:成功处理了部分请求
3xx 通常表示重定向,通常表示请求的内容已经不在目标位置,已经被转移到了新的位置,以便于告诉客户端去新的地方寻找。
300:请求会有多种选择,需要根据 User-Agent 来进行下一步操作
301:请求的网页已经永久移动到了另一个地方
302:请求的网页临时移动到了一个新的地方
4xx 通常表示客户端发生错误,导致请求出现问题。
400:请求错误,服务器无法理解请求的内容
401:请求没有进行身份验证,是不被许可的请求
403:请求被拒绝
404:请求了目标网页,但是没有找到这个网页,网页不存在
405:请求的时候使用的方法是被禁止的
422:服务器虽然理解了请求的内容,但是请求包含的信息不合逻辑,导致服务器无法处理请求
5xx 通常表示服务器发生错误,服务器正确接受了请求,但是服务器内部产生了错误导致请求无法正常响应
500:服务器内部错误
503:服务器不可用
在 python 中,对于请求得到的 response 对象,可以使用 response.status_code
来获取状态码:
xxxxxxxxxx
print(response.status_code)
得到的输出结果是:
xxxxxxxxxx
200
对于响应的内容,有两种获取的方式,分别是:response.text
和 response.content
,下面对这两种方法进行简单的介绍和演示:
response.text
用于以文本的形式来获取网页的内容,对于网页来说通常是以 html 代码的形式来返回:
xxxxxxxxxx
print(response.text)
得到的结果(这里结果是上面的 get 请求的结果,网页是特殊的,因为这个网页对应的内容很短。实际上一般来说这样获取并且直接打印是不常见的,因为内容非常长):
xxxxxxxxxx
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>页é¢æ•£å¨å¶ä½...</title>
</head>
<body>
<h1>页é¢æ•£å¨å¶ä½ä¸•......</h1>
<a href="./index.html">è¿å主页>></a>
</body>
</html>
这里的响应是 html 代码,用来让浏览器理解网页的内容,但是这里不难发现全都是乱码,具体原因和解决办法将在 2.4 讲解。
response.content
用于以二进制的形式来获取网页的内容,一般来说通常是获取图片、音乐等这种二进制内容
xxxxxxxxxx
print(response.content)
得到的结果:
xxxxxxxxxx
b'<html>\r\n <head>\r\n <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">\r\n <title>\xe9\xa1\xb5\xe9\x9d\xa2\xe6\xad\xa3\xe5\x9c\xa8\xe5\x88\xb6\xe4\xbd\x9c...</title>\r\n </head>\r\n\r\n <body>\r\n <h1>\xe9\xa1\xb5\xe9\x9d\xa2\xe6\xad\xa3\xe5\x9c\xa8\xe5\x88\xb6\xe4\xbd\x9c\xe4\xb8\xad......</h1>\r\n <a href="./index.html">\xe8\xbf\x94\xe5\x9b\x9e\xe4\xb8\xbb\xe9\xa1\xb5>></a>\r\n </body>\r\n</html>'
通常这种内容我们是很难直接看出来的,所以一般来说是用于接收文件之类的操作,要配合文件读写,下面是从我的服务器下载一张图片的代码:
xxxxxxxxxx
# 导入 requests 用于发送网页请求
import requests
# 要爬取的网页
url = "http://ky0ha.com/image/logo.png"
# 使用 requests 发送 get 请求,请求目标是 url 变量内字符串对应的网页
response = requests.get(url=url)
# 打开一个文件来写入接收到的图片文件的内容,需要使用 wb 模式来二进制打开并写入
with open("logo.png", "wb") as f:
# 以二进制获取请求到的内容(图片),并写入文件
f.write(response.content)
响应到的内容,我们使用文本形式获取的时候,发现了乱码,这个原因是因为响应的内容编码不是我们通常使用的、支持中文的 utf-8 编码。所以我们需要单独设置编码格式:
xxxxxxxxxx
response.encoding = 'utf-8'
通过将上面的代码放在使用 response.text
获取网页内容之前,可以发现编码的问题已经成功修复:
xxxxxxxxxx
# 设置编码格式
response.encoding = 'utf-8'
# 获取内容并输出
print(response.text)
输出结果:
xxxxxxxxxx
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>页面正在制作...</title>
</head>
<body>
<h1>页面正在制作中......</h1>
<a href="./index.html">返回主页>></a>
</body>
</html>
当我们获取到一个 html 文本之后,直接对这个文本进行索引取值,或者其他的方式来直接获取到我们想要的信息是非常难,可以说是不可能的,所以我们要使用一个专门的模块来做这件事情,这个模块的名字叫 BeautifulSoup4 ,下载方式是使用 pip 下载:
xxxxxxxxxx
pip install bs4
下载完成之后,使用下面的方式导入:
xxxxxxxxxx
# 注意 BeautifulSoup 的拼写,B 和 S 是大写
from bs4 import BeautifulSoup
BeautifulSoup 解析器的使用方式是,直接调用 BeautifulSoup
函数,来对 html 文本进行解析:
xxxxxxxxxx
# 将网页内容解析之后,将解析后的结果放入 content 变量内
content = BeautifulSoup(response.text, "html.parser")
BeautifulSoup 的第一个参数是文本形式的 html 内容,第二个参数固定是 "html.parser"
,表示要解析 html 文本。解析后会将解析结果返回出来,在上面的代码中,解析结果会被保存在 content
变量内。
首先我们要了解一下 html 的基本结构:标签。html 的标签通常由以下几个部分构成:
这里的 id 和 class 用于特殊标注这个标签,这也是我们使用解析器找到我们想要爬取的内容的关键途径。
那么我们如何知道我们想要找到的东西在哪里呢?这个时候就要用到浏览器的 “检查” 功能了。随便打开一个网页(这里用我的服务器 http://ky0ha.com/github_style_project.html 来举例。
这里是网页中的一个表,假设我们需要获取这个表当中的第一列的所有名称,这就是我们需要的数据。那么我们可以选择到某一个需要获取的具体的数据,然后点击右键,选择最下面的检查:
点击检查之后,会在右边出现一个新的东西:
这个新的区域,我们称之为调试窗口。在调试窗口内,我们可以查看到上图的这一部分的代码,被称之为 html 代码,我们可以通过将想要的目标选中并点击检查,来快速找到它在 html 中的位置。
上图中,我们不难发现我们想要的 “关键字” 这三个字在一个叫做 td 的标签内,而且这个标签具有一个属性 class="type"
。这个 td 标签在 tr 标签内,tr 在 tbody 内,tbody 在 table 内,这个 table 具有属性 class="color_table"
。这些属性和标签可以帮助我们快速找到我们需要的内容。
我们之前使用 content = BeautifulSoup(response.text, "html.parser")
得到的解析结果 content
是一个特殊的对象,它有很多好用的方法,我们只介绍其中最简单的两个方法,它们可以帮助我们找到我们想要的东西。
我们想要找到某个特定的标签,需要使用 find
来进行这种操作。find 的常见使用方式是:xxx.find("标签名", id="id 属性", class_="class 属性")
,这里的 id 和 class_ 参数是可以省略的,具体是否写,写哪个,按照实际情况来选择。易错点:当我们想要利用 class 属性来找某个标签的时候,在代码中需要使用 class_
参数,不要忘记下划线
比如我们尝试获取上面的 <table class="color_table">
这个标签。
xxxxxxxxxx
import requests
from bs4 import BeautifulSoup
url = "http://ky0ha.com/github_style_project.html"
response = requests.get(url=url)
response.encoding = 'utf-8'
content = BeautifulSoup(response.text, "html.parser")
target = content.find("table", class_="color_table")
print(target)
得到的结果通过 print 输出后,我们可以看到(由于太长,中间部分省略):
xxxxxxxxxx
<table class="color_table">
<tr>
<td class="type">类型</td>
<td class="name">定义名称</td>
<td class="color_number">色号</td>
<td class="color_style0">颜色</td>
</tr>
<tr>
<td class="type">关键字</td>
<td class="name">value</td>
<td class="color_number">rgb(255,123,144)</td>
<td class="color_style1"></td>
</tr>
.
.
.
</tr>
<tr>
<td class="type">超链接</td>
<td class="name">href_link</td>
<td class="color_number">rgb(165,214,255)</td>
<td class="color_style6"></td>
</tr>
</table>
如果 find 方法未找到目标标签,会返回 None 作为结果。
使用 find 方法只能找到一个,所以通常我们也会使用 find_all 来一次性找到所有符合条件的标签,每找到一个都会将其作为一个元素,将这些元素组合成一个列表。当没找到的时候,会返回空列表;如果只找到一个符合要求的标签,会得到一个只有一个元素的列表。注意!find 得到的是一个标签对象,find_all 得到的是一个列表
接下来我们使用我们刚刚得到的 table 标签来进一步筛选(套娃)。通过前面的内容,我们可以不难发现我们要的东西在 table 里面的 tr 里面的 td 里面。我们可以使用 find_all 来找到所有的 tr 标签:
xxxxxxxxxx
target = target.find_all("tr")
print(target)
观察一下输出的结果(太长所以中间省略):
xxxxxxxxxx
[<tr>
<td class="type">类型</td>
<td class="name">定义名称</td>
<td class="color_number">色号</td>
<td class="color_style0">颜色</td>
</tr>, <tr>
<td class="type">关键字</td>
<td class="name">value</td>
<td class="color_number">rgb(255,123,144)</td>
<td class="color_style1"></td>
</tr>,
.
.
.
<tr>
<td class="type">超链接</td>
<td class="name">href_link</td>
<td class="color_number">rgb(165,214,255)</td>
<td class="color_style6"></td>
</tr>]
我们获得了里面的每一个 tr 标签,并把每个 tr 标签单独作为一个元素来保存在列表内。这样我们就可以索引取值或者循环遍历,来对里面的每一个 tr 标签获取想要的内容。
接下来我们可以看到我们要的就在每一个 tr 标签内的第一个 td 标签,我们结合前面的内容,可以想到有多种方法来进行这一步的筛选:
使用 find 并利用 class 属性来筛选
xxxxxxxxxx
import requests
from bs4 import BeautifulSoup
url = "http://ky0ha.com/github_style_project.html"
response = requests.get(url=url)
response.encoding = 'utf-8'
content = BeautifulSoup(response.text, "html.parser")
target = content.find("table", class_="color_table")
target = target.find_all("td", class_="type")
# 遍历所有的 tr 标签
for i in target:
# 使用 find 来根据 class 标签找到我们想要的标签,并将这个标签放在 item 变量内
item = i.find("td", class_="type")
# 打印 item 变量便于我们验证结果
print(item)
输出的结果是:
xxxxxxxxxx
<td class="type">类型</td>
<td class="type">关键字</td>
.
.
.
<td class="type">超链接</td>
可以看到我们确实是得到了我们要的内容,得到了每一个 td 标签,但是我们 td 标签里面面得到的有表头,也就是内容为 ”类型“ 的那一项,所以我们可以在遍历开始的时候就去掉第一项:
xxxxxxxxxx
# 遍历所有的 tr 标签,利用索引切片来去掉了第一项
for i in target[1:]:
# 使用 find 来根据 class 标签找到我们想要的标签,并将这个标签放在 item 变量内
item = i.find("td", class_="type")
# 打印 item 变量便于我们验证结果
print(item)
接下来我们可以对我们单独遍历取到的每一个 td 标签,来获取到里面的文本内容,我们需要使用到 text 属性来获取:
xxxxxxxxxx
# 遍历所有的 tr 标签,利用索引切片来去掉了第一项
for i in target[1:]:
# 使用 find 来根据 class 标签找到我们想要的标签,并将这个标签放在 item 变量内
item = i.find("td", class_="type")
# 打印 item 变量便于我们验证结果
print(item.text) # 通过 text 来获取文本内容
输出的结果是:
xxxxxxxxxx
关键字
运算符
.
.
.
超链接
使用 find_all 加 class 标签
xxxxxxxxxx
import requests
from bs4 import BeautifulSoup
url = "http://ky0ha.com/github_style_project.html"
response = requests.get(url=url)
response.encoding = 'utf-8'
content = BeautifulSoup(response.text, "html.parser")
target = content.find("table", class_="color_table")
target = target.find_all("td", class_="type")
print(target)
输出结果是:
xxxxxxxxxx
[<td class="type">类型</td>, <td class="type">关键字</td>, <td class="type">运算符</td>, <td class="type">单位</td>, <td class="type">值</td>, <td class="type">默认函数</td>, <td class="type">属性</td>, <td class="type">注释</td>, <td class="type">自定义函数</td>, <td class="type">类名</td>, <td class="type">字符串</td>, <td class="type">标签</td>, <td class="type">超链接</td>]
遍历除去第一个之后的每一个元素,使用 text 获取内容:
xxxxxxxxxx
for i in target[1:]:
print(i.text)
输出的结果是:
xxxxxxxxxx
关键字
运算符
.
.
.
超链接
这里我们将要使用 https://lishi.tianqi.com/songjiang/index.html 来获取松江的 11 月天气:
xxxxxxxxxx
import requests
from bs4 import BeautifulSoup
url = "https://lishi.tianqi.com/songjiang/index.html"
response = requests.get(url=url)
response.encoding = 'utf-8'
print(response.status_code)
print(response.text)
首先我们来获取到网页内容并打印看一下:
xxxxxxxxxx
403
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>403 Forbidden</title></head><body><h1>403 Forbidden</h1><p>You don't have permission to access the URL on this server.</p><p>denied by UA ACL = blacklist</p><hr/>Powered by Tengine <br/>CDN Request Id: 8be3e61517308611937218205e</body></html>
我们会发现无法正常获取,返回的状态码是 403,拒绝访问,这里的原因是因为网页的服务器发现我们是利用爬虫进行的非正常访问,所以不让我们访问,拒绝了我们的请求。解决这个问题的方式是加入头部信息 headers,在头部信息中使用 User-Agent 来告诉服务器我们的信息(相当于给服务器自我介绍)。
我们可以右键检查,打开调试控制台,在上面选择 network 网络选项,并点击 ctrl+r 来刷新网页。
将下面的表格滑动到最上面,点击 Index.html 这一条,在弹出的窗口中划到最底下,看一下最下面的一条 User-Agent。
将里面的内容复制,并在代码中创建一个字典来代表这个头部信息:
xxxxxxxxxx
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}
将这个变量传递给 get 请求,来伪装自己的爬虫请求:
xxxxxxxxxx
import requests
from bs4 import BeautifulSoup
url = "https://lishi.tianqi.com/songjiang/index.html"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}
response = requests.get(url=url, headers=headers)
response.encoding = 'utf-8'
print(response.status_code)
查看输出(这里只输出状态码,不然整个网页的内容太长,不方便查看):
xxxxxxxxxx
200
成功获取输出。接下来通过右键检查,分析网页内容:
xxxxxxxxxx
# 导入网页请求模块 requests
import requests
# 导入 bs4 用于分析网页内容
from bs4 import BeautifulSoup
# 定义 url 变量为我们需要爬取的网页网址
url = "https://lishi.tianqi.com/songjiang/index.html"
# 定义头部信息 headers,用里面的 User-Agent 来欺骗服务器
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}
# 发送请求
response = requests.get(url=url, headers=headers)
# 设置编码格式,避免乱码
response.encoding = 'utf-8'
# 使用 bs4 分析网页内容,将分析结果保存在 content
content = BeautifulSoup(response.text, "html.parser")
# 使用 find 利用 class 来获取 ul 标签
tianqi_list = content.find('ul', class_="tian_two")
# 找到 ul 标签内所有的包含了数字信息的标签 div
numbers = tianqi_list.find_all("div", class_="tian_twoa")
# 找到 ul 标签内所有的包含了文字信息的标签 div
labels = tianqi_list.find_all("div", class_="tian_twob")
# 遍历这两个列表,使用 zip 将两个列表按照索引拼接在一起,使用 number 和 label 遍历
for number, label in zip(numbers, labels):
# 利用 f-string 格式化输出
print(f"{label.text}:{number.text}")
输出结果:
xxxxxxxxxx
平均高温:23℃
平均低温:16℃
极端高温:31℃
极端低温:11℃
平均空气质量指数:50
空气最好(10/26):19
空气最差10/10):81
从网页获取数据内容除了以 text
和 content
返回文本形式和二进制形式以外,还有一种特殊的返回形式:json 返回形式。
json 是一种特殊的文件格式,全程是 JavaScript Object Notation,JavaScript对象表示法。它是一种 主要用于网络数据传输的轻量文本格式 。通俗理解,我们可以直接将它认为是 python 的字典。
我们打开浏览器,搜索百度图片,进入百度图片官方主页:
在上面的搜索栏输入 “柯南”,点击百度一下,就可以看到我们想要的图片了:
接下来我们需要打开 开发者模式 ,有三种方式打开开发者模式:
点击键盘上的 f12
右键单击网页,点击 “检查”
点击网页右上角三个点——更多工具——开发者工具
打开之后的会弹出一个窗口,点击上方的 Network(网络),会显示下面有很多内容的一个表格,如下图:
接下来在下面选择 Fetch/XHR
,如果出现下图这种空白的情况,需要点击 Ctrl + R
键重新刷新网页:
如果像下面一样刷新之后没有出现名为 acjson?
开头的内容,那么就去网页里面,往下滑一下:
成功出现 acjson?
开头的内容后,单击打开第一个 acjson?
开头的请求的内容,重点查看红色框起来的部分,将这部分网页复制下来:
将这个网址复制到代码当中,使用 requests 向这个页面发送一个 get 请求:
xxxxxxxxxx
import requests
url = "https://image.baidu.com/search/acjson?tn=resultjson_com&logid=9483569850552987050&ipn=rj&ct=201326592&is=&fp=result&fr=&word=%E6%9F%AF%E5%8D%97&queryWord=%E6%9F%AF%E5%8D%97&cl=2&lm=&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=30&rn=30&gsm=1e&1731243132063="
response = requests.get(url)
print(response.text)
输出的结果会是:
xxxxxxxxxx
{"antiFlag":1,"message":"Forbid spider access","bfe_log_id":"10558288220929577468"}
是不是看不懂?别急,我们先来看看我们的网页。点击刚刚显示网页上面的 Preview 预览,打开预览之后,可以看到下面是字典的键和值,这里 data 就是我们需要的东西,左键点开 data 看看,就可以看到里面的每个图片的具体数据了:
这里的 data 对应的值是一个列表,列表里每个元素是一个字典,字典里面存储的是我们的图片信息。但是!注意!我们会发现我们在网页中看到的字典和我们自己爬虫获得的字典完全不是一个样子的! 这里的原因在于,百度图片发现我们是爬虫,不是真正的浏览器,所以不给我们真正的信息,所以我们需要伪装我们自己的爬虫,才能获得我们要的内容。
我们需要设置 hearders(前面已经介绍过,这里不再赘述)。
xxxxxxxxxx
import requests
url = "https://image.baidu.com/search/acjson?tn=resultjson_com&logid=9483569850552987050&ipn=rj&ct=201326592&is=&fp=result&fr=&word=%E6%9F%AF%E5%8D%97&queryWord=%E6%9F%AF%E5%8D%97&cl=2&lm=&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=30&rn=30&gsm=1e&1731243132063="
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}
response = requests.get(url)
print(response.text)
获得的结果如下(因为太长后面省略):
x{"queryEnc":"%BF%C2%C4%CF","queryExt":"柯南","listNum":1797,"displayNum":626689,"gsm":"3c","bdFmtDispNum":"约626,000","bdSearchTime":"","isNeedAsyncRequest":0,"bdIsClustered":"0","data":[{"aiEditData": { "text": "图片编辑", "type": "-1" }...
终于我们成功获得了我们用于获取 json 内容的网址,并且成功获取到了我们要的 json内容。
但是这里,我们如果使用 type 函数查看一下我们获取到的这些 json 的类型,我们会发现它是一个字符串类型,这明显不是我们想要的字典类型:
xxxxxxxxxx
print(type(response.text))
输出:
xxxxxxxxxx
<class 'str'>
那么如何才能以 json 的形式,或者说以字典的形式返回我们的 json 内容呢?这时候我们就要用到 requests.json()
方法了。
这里我们使用这个方法之后,打印查看这个方法返回值的类型和内容:
xxxxxxxxxx
print(type(response.json()))
print(response.json())
输出:
xxxxxxxxxx
<class 'dict'>
{"queryEnc":"%BF%C2%C4%CF","queryExt":"柯南","listNum":1797,"displayNum":626689,"gsm":"3c","bdFmtDispNum":"约626,000","bdSearchTime":"","isNeedAsyncRequest":0,"bdIsClustered":"0","data":[{"aiEditData": { "text": "图片编辑", "type": "-1" }...
这里我们发现得到的结果是一个字典了,我们就可以比较轻松的使用索引取值的方式找到我们想要的内容了。
接下来我们回到网页中,去分析一下这个字典的结构,从之前的内容不难得出我们想要的图片内容在字典当中是 data
这个键对应的值,所以我们需要使用索引取值去尝试获取我们需要的内容。
x
data = response.json()['data']
这样我们就将整个图片的信息的列表放在了 data 变量里面。接下来我们可以回到浏览器,分析一下这个列表里面每个元素的内容,看看我们需要的图片的内容在哪里。随便单击点开列表的一条元素:
我们首先可以看到的是,列表的每个元素又是一个字典,并且这个字典里面有一个叫做 hoverURL
的键,我们将对应的值,也就是后面这串网址复制到浏览器里面打开,我们就会发现这就是我们想要的图片。那么如何获得换个网址呢?相信从前面的过程来看,内心应该已经有答案了——字典的索引取值。我们用键 hoverURL
来取值即可。
x
# 索引遍历 data 列表,由于只有 30 条记录,第 31 条是空的,所以我们这里 range 只取 30
for i in range(30):
# 获取到图片网址
img_url = data[i]['hoverURL']
# 打印输出
print(img_url)
输出的结果看起来会比较多,所以只显示一小部分:
xxxxxxxxxx
https://img2.baidu.com/it/u=3493398252,4162067230&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=500
https://img2.baidu.com/it/u=4080758464,3543096333&fm=253&fmt=auto&app=120&f=JPEG?w=667&h=500
https://img2.baidu.com/it/u=3072194843,220504003&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500
...
接下来我们只需要再用一次 requests 来获取到图片网址的内容,也就是对应的图片之后,保存图片即可,首先我们获取到我们的图片内容:
x
# 不要忘记用 headers 伪装自己
img = requests.get(img_url, headers=headers)
# 使用 content 获取二进制内容作为结果
img = img.content
# 打开文件并写入 img,文件名就是索引
with open(f"{i}.jpeg", 'wb') as f:
f.write(img)
这里我们通过 content 获取到二进制形式的内容,也就是图片内容之后,我们用二进制写将图片写入了文件中,文件的名称是索引加上 .jepg 后缀,文件的位置和代码在同一位置,我们也可以创建一个文件夹,使得我们的文件不会到处乱跑:
x
# 不要忘记用 headers 伪装自己
img = requests.get(img_url, headers=headers)
# 使用 content 获取二进制内容作为结果
img = img.content
# 打开文件并写入 img,文件名就是索引,这里需要和代码在一起的地方有一个 pic 文件夹才可以
with open(f"./pic/{i}.jpeg", 'wb') as f:
f.write(img)
我们通过这种方式将图片全部保存在了对应的位置:
xxxxxxxxxx
import requests
url = "https://image.baidu.com/search/acjson?tn=resultjson_com&logid=9374917970643748622&ipn=rj&ct=201326592&is=&fp=result&fr=&word=%E6%9F%AF%E5%8D%97&queryWord=%E6%9F%AF%E5%8D%97&cl=2&lm=&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=30&rn=30&gsm=1e&1731481446170="
headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}
response = requests.get(url, headers=headers)
data = response.json()['data']
# 索引遍历 data 列表,由于只有 30 条记录,第 31 条是空的,所以我们这里 range 只取 30
for i in range(30):
# 获取到图片网址
img_url = data[i]['hoverURL']
# 不要忘记用 headers 伪装自己
img = requests.get(img_url, headers=headers)
# 使用 content 获取二进制内容作为结果
img = img.content
# 打开文件并写入 img,文件名就是索引,这里需要和代码在一起的地方有一个 pic 文件夹才可以
with open(f"./pic/{i}.jpeg", 'wb') as f:
f.write(img)
如果我们仔细观察下面的网址,我们可以看到里面的内容有一些有趣的地方,那就是图片的文件格式的部分:
xxxxxxxxxx
https://img2.baidu.com/it/u=1303539814,1878265049&fm=253&fmt=auto&app=120&f=JPEG?w=801&h=500
我们观察后面的部分,有段 f=JPEG
,这里的 JPEG 实际上就是文件的格式,所以我们可以通过尝试获取到这段字符串来自动分析我们的图片的后缀名,这样可以避免格式错误。这部分属于拓展部分,我直接给出完整代码:
xxxxxxxxxx
import requests
url = "https://image.baidu.com/search/acjson?tn=resultjson_com&logid=9374917970643748622&ipn=rj&ct=201326592&is=&fp=result&fr=&word=%E6%9F%AF%E5%8D%97&queryWord=%E6%9F%AF%E5%8D%97&cl=2&lm=&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=©right=&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&expermode=&nojc=&isAsync=&pn=30&rn=30&gsm=1e&1731481446170="
headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"}
response = requests.get(url, headers=headers)
data = response.json()['data']
# 索引遍历 data 列表,由于只有 30 条记录,第 31 条是空的,所以我们这里 range 只取 30
for i in range(30):
# 获取到图片网址
img_url = data[i]['hoverURL']
# * 获取后缀名
suffix = img_url.split('&')[4].split('?')[0][2:].lower()
# 不要忘记用 headers 伪装自己
img = requests.get(img_url, headers=headers)
# 使用 content 获取二进制内容作为结果
img = img.content
# 打开文件并写入 img,文件名就是索引,这里需要和代码在一起的地方有一个 pic 文件夹才可以
with open(f"./pic/{i}.{suffix}", 'wb') as f:
f.write(img)