本篇是python爬虫之 爬取案例网页ajax请求的数据2之 跳转url下载图片_水w的博客-CSDN博客的后续补充。
在前文的基础上,我们已经爬取到了第一个ajax请求下我们想要爬取的logo生成url地址,接下来我想要爬取后续所有的ajax请求下我们想要爬取的logo生成url地址,并且下载这些图片。
思路和步骤:
再进一步,我们通过这些有规律的变化来改变参数,进而达到模拟用户点击“加载更多”这一操作,爬取更多的logo图片。
那么我们就开始在上一篇写的代码的基础上,进行改进。
(1)创建一个LogoSpider类之后,我们现在先对该项目进行分析,分析主要大致需要哪几个函数,每个函数具体需要实现的功能是什么,先大概说明一下。
class LogoSpider():
def __init__(self):
self.version = ''
def get_json(self,page):
"""拿到ajax请求的保存logo图片信息的json"""
pass
def save_img(self,image_id, image_url):
"""保存图片"""
pass
def main(self,page):
"""主函数"""
pass
(2)在创建号类和分析函数的功能之后,我们接下来就开始编写代码了。
首先先编写get_json()函数,功能是拿到ajax请求的logo图片信息的json。
在这个函数中,我们需要对现在是第几次ajax请求进行区分,因为如果不是第1次的ajax请求的时候,会比第1次ajax请求不仅page参数变化了,而且多了一个参数version。
我们需要根据相应的第几次ajax请求,来改变我们的请求参数params。
ajax请求的logo图片信息的json格式的数据,如图所示:
get_json()函数代码:
def get_json(self,page):
"""拿到ajax请求的保存logo图片信息的json"""
if page == 1:
params = {
"brandName": "小天才",
"slogan": "Genius",
"keywords": "互联网",
"industryName": "软件和信息技术服务业",
"industryId": 49,
"sceneId": 2,
"page": 1,
}
else:
# 之后的ajax请求变化的参数:page++,version
params = {
"brandName": "小天才",
"slogan": "Genius",
"keywords": "互联网",
"industryName": "软件和信息技术服务业",
"industryId": 49,
"sceneId": 2,
"page": page,
"version":self.version,
}
# 拼接参数
url = base_url + urlencode(params)
try:
response = requests.get(url,headers=headers)
if response.status_code==200:
return response.json()
except requests.ConnectionError as e:
print("Error",e.args)
(2)编写save_img()函数,主要功能是通过请求解析出来的每一个logo图片的url,来获取到logo图片,并保存到文件夹中。
在这个函数中,调用了全局变量sum_success,用来记录目前已经有多少图片下载完成。
save_img()函数代码:
def save_img(self,image_id, image_url):
"""通过请求解析出来的每一个logo图片的url,来获取到logo图片,并保存到文件夹中。"""
global sum_success
print('正在下载image_id为',image_id)
try:
if not os.path.exists(IMAGE_SRC):
os.mkdir(IMAGE_SRC)
filename = IMAGE_SRC + image_id + '.jpg'
#如果图片已经存在了,跳过本次循环
if not os.path.exists(filename):
# 下载图片,并保存到文件夹中
urllib.request.urlretrieve(image_url, filename=filename)
print('*******图片image_id为' + str(image_id) + '下载完成')
sum_success += 1
else:
print('**********此图片已存在')
except IOError as e:
print('保存图片出现异常失败!', e)
(3)编写main()函数,主要功能是从get_json()函数拿到获取的json格式数据,对数据进行处理和解析,将页面生成的logo图片的url保存到队列中,从队列中每次取出一个url,调用save_img()函数保存logo图片到文件夹。
主要功能是:
1.从get_json()函数拿到获取的json格式数据;
2.对数据进行处理和解析;
3.将页面生成的logo图片的url保存到队列中;
4.从队列中每次取出一个url,调用save_img()函数保存logo图片到文件夹。
补充知识:
1、queue标准库
from queue import Queue
data_queue = Queue() # 创建队列
data_queue.qsize() # 队列大小
data_queue.put(10) # 将10入队
data_queue.get() # 出队操作,并返回队首元素
data_queue.empty() # 判断队列是否为空
2、os.path.exists()函数:
os.path模块主要用于文件的属性获取,因此这个函数的功能就是判断文件当前是否存在。
os.path.exists([文件的路径])
如果返回False,那么说明以该文件名命名的文件当前不存在,需要使用os.mkdir()函数以这个文件名来创建一个新的文件。
3、urllib.request.urlretrieve()函数:
利用urlretrieve()函数可以将数据下载到本地。
参数:
- url:需要request请求的url地址(即需要获取数据的地址)
在本篇中,url为每一个logo图片的url
- filename:将请求获取的数据存放入的文件名在本篇中,filename为“IMAGE_SRC + image_id + '.jpg'”
- reporthook:是一个回调函数,当连接上服务器、以及相应的数据块传输完毕时会触发该回调,我们可以利用这个回调函数来显示当前的下载进度
- data:指post导服务器的数据,该方法返回一个包含两个元素的(filename, headers) 元组,filename 表示保存到本地的路径,header表示服务器的响应头
使用方法:
urllib.request.urltrieve(url,filename=None,reporthook=None,data=None)
main()函数代码:
def main(self,page):
""" 1.从get_json()函数拿到获取的json格式数据
2.对数据进行处理和解析
3.将页面生成的logo图片的url保存到队列中
4.从队列中每次取出一个url,调用save_img()函数保存logo图片到文件夹
"""
j = self.get_json(page)
# print(j)
try:
# 得到下一个ajax请求的version参数
self.version = j['data']['images']['version']
print('version:',self.version)
# 将每一个logo图片的url和id数据解析出来,并以字典格式放入队列中保存
for goods in j['data']['images']['list']:
# print({'id':goods['goodsId'],'url':goods['url']})
data_queue.put({"id":goods['goodsId'],"url":goods['url']})
global sum_success
# 当队列为空时,才停止
while data_queue.empty() != True:
# 从队列中取出一个图片信息的字典格式
image = data_queue.get()
self.save_img(image_id=image['id'],image_url=image['url'])
print(">>>>>>>>>>>>>>>已有"+ str(sum_success) +"个下载成功")
time.sleep(1)
else:
print("data_queue队列为空!")
except Exception as err:
print('出现异常:',err)
(4)完整代码:
from ensurepip import version
from urllib.parse import urlencode
from pyquery import PyQuery as pq
from bs4 import BeautifulSoup
import re,bs4,json,socket,random,os,requests,threading,time,urllib
from queue import Queue
base_url = "https://logo.aliyun.com/logo/buildGoodsList.json?"
headers = {
"cookie": "cna=liaPF6GPZ0cCAXuuxE6TaBwc; aliyun_choice=CN; _uab_collina=165174083869593284740835; t=c68c60f79656b6361d4c3299eceefb0d; login_aliyunid_pk=1934551737570629; userViewed=aliyun745882****; aliyun_lang=zh; XSRF-TOKEN=1972b755-e958-4330-86e7-3777d4ab992d; _samesite_flag_=true; cookie2=1da4afe997cab48cc14db3f3c107e487; _tb_token_=e345333e7a7e3; _hvn_login=6; csg=e7a351ed; login_aliyunid=\"aliyun745882****\"; login_aliyunid_ticket=XXZQg4KFWufyvpeV*0*Cm58slMT1tJw3_p$$_29heKupjCAXonKn8srwMrwdWdmdfARMiNcYT7KgxVof_BNpwU_TOTNChZBoeM1KJexdfb9zhYnsN5Zos6qISCrRt7mGxbigG2Cd4fWaCmBZHIzsgd6q0; login_aliyunid_csrf=_csrf_tk_1567151892930436; hssid=1R5BQXbbgg6ZI2G5RDYuPlQ1; hsite=6; aliyun_country=CN; aliyun_site=CN; JSESSIONID=B2DD0AEF589EBA595F400F5B4BC1A34F; isg=BLOzZloi1S8TaJmg6Uvv2hRxQrfd6EeqrRu0HWVQD1IJZNMG7bjX-hH1H5SKEZ-i; l=eBN9iCerLSmJGNcKBOfahurza77OSIRvWuPzaNbMiOCPOV5B5sqfW645E5T6C3hVh68HR3Jfz-p8BeYBqQd-nxv96aiE7Vkmn; tfstk=c3zPBbTpSaQykF0CX4gFdNR7DRPRZ0HnCElZqOvgx4W1DXoliIvKixQtgXR2K0f..",
"referer": "https://logo.aliyun.com/logo?msctype=email&mscareaid=cn&mscsiteid=cn&mscmsgid=9140122032200691186&spm=a2c4l.26849360.zh-cnc.1&accounttraceid=76ef6c44de72465daef048c81127602enspq",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"
}
# 存储图片的位置 D:\大学\实习方面\BaiduSpider\LogoSpider\logo
IMAGE_SRC = 'D://大学/实习方面/BaiduSpider/LogoSpider/logo/'
# 使用队列保存存放图片的id和url地址, 确保线程同步
data_queue = Queue()
sum_success = 0
sum_failed = 0
class LogoSpider():
def __init__(self):
self.version = ''
def get_json(self,page):
"""拿到ajax请求的保存logo图片信息的json"""
if page == 1:
params = {
"brandName": "小天才",
"slogan": "Genius",
"keywords": "互联网",
"industryName": "软件和信息技术服务业",
"industryId": 49,
"sceneId": 2,
"page": 1,
}
else:
# 之后的ajax请求变化的参数:page++,version
params = {
"brandName": "小天才",
"slogan": "Genius",
"keywords": "互联网",
"industryName": "软件和信息技术服务业",
"industryId": 49,
"sceneId": 2,
"page": page,
"version":self.version,
}
# 拼接参数
url = base_url + urlencode(params)
try:
response = requests.get(url,headers=headers)
if response.status_code==200:
return response.json()
except requests.ConnectionError as e:
print("Error",e.args)
def save_img(self,image_id, image_url):
"""保存图片"""
global sum_success
print('正在下载image_id为',image_id)
try:
if not os.path.exists(IMAGE_SRC):
os.mkdir(IMAGE_SRC)
filename = IMAGE_SRC + image_id + '.jpg'
#如果图片已经存在了,跳过本次循环
if not os.path.exists(filename):
# 下载图片,并保存到文件夹中
urllib.request.urlretrieve(image_url, filename=filename)
print('*******图片image_id为' + str(image_id) + '下载完成')
sum_success += 1
else:
print('**********此图片已存在')
except IOError as e:
print('保存图片出现异常失败!', e)
def main(self,page):
j = self.get_json(page)
# print(j)
try:
# 得到下一个ajax请求的version参数
self.version = j['data']['images']['version']
print('version:',self.version)
# 将每一个logo图片的url和id数据解析出来,并以字典格式放入队列中保存
for goods in j['data']['images']['list']:
# print({'id':goods['goodsId'],'url':goods['url']})
data_queue.put({"id":goods['goodsId'],"url":goods['url']})
global sum_success
# 当队列为空时,才停止
while data_queue.empty() != True:
# 从队列中取出一个图片信息的字典格式
image = data_queue.get()
self.save_img(image_id=image['id'],image_url=image['url'])
print(">>>>>>>>>>>>>>>已有"+ str(sum_success) +"个下载成功")
time.sleep(1)
else:
print("data_queue队列为空!")
except Exception as err:
print('出现异常:',err)
if __name__ == '__main__':
logospider = LogoSpider()
page = 3 # 起始ajax请求数
logospider.version = '这块儿写爬取到的version'
# 对前3个ajax请求进行爬取
while page<= 6:
logospider.main(page)
page += 1
在vscode新建终端,在终端输入命令执行代码:
python spide.py
(5)vscode的终端显示这张图片已经成功下载了,具体的生成结果如下:
一共发送了4次ajax请求,下载了108张图片(这里截图不完整)
我们随便打开一张图片,如下图所示:
OK,那么我们今天就到这里了!!