python爬虫之 爬取案例网页ajax请求的数据3之 实现跨页爬取

本篇是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,那么我们今天就到这里了!!

猜你喜欢

转载自blog.csdn.net/qq_45956730/article/details/124665773
今日推荐