• Python爬虫入门教程 7-100 蜂鸟网图片爬取之二


    蜂鸟网图片--简介

    今天玩点新鲜的,使用一个新库 aiohttp ,利用它提高咱爬虫的爬取速度。

    安装模块常规套路

    pip install aiohttp
    

    在这里插入图片描述

    运行之后等待,安装完毕,想要深造,那么官方文档必备 :https://aiohttp.readthedocs.io/en/stable/

    接下来就可以开始写代码了。

    我们要爬取的页面,这一次选取的是

    http://bbs.fengniao.com/forum/forum_101_1_lastpost.html
    

    打开页面,我们很容易就获取到了页码

    在这里插入图片描述
    好久没有这么方便的看到页码了。

    尝试用 `aiohttp` 访问这个页面吧,模块的引入,没有什么特殊的,采用 `import` 即可 如果我们需要 使用`Asyncio + Aiohttp`异步IO 编写爬虫,那么需要注意,你需要异步的方法前面加上`async`

    接下来,先尝试去获取一下上面那个地址的网页源码。

    代码中,先声明一个fetch_img_url的函数,同时携带一个参数,这个参数也可以直接写死。

    with 上下文不在提示,自行搜索相关资料即可 (`・ω・´)

    aiohttp.ClientSession() as session: 创建一个session对象,然后用该session对象去打开网页。session可以进行多项操作,比如post, get, put

    代码中 await response.text() 等待网页数据返回

    asyncio.get_event_loop创建线程,run_until_complete方法负责安排执行 tasks中的任务。tasks可以为单独的函数,也可以是列表。

    import aiohttp  
    import asyncio 
    
    
    async def fetch_img_url(num):
        url = f'http://bbs.fengniao.com/forum/forum_101_{num}_lastpost.html'  # 字符串拼接
        # 或者直接写成 url = 'http://bbs.fengniao.com/forum/forum_101_1_lastpost.html'
        print(url)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6726.400 QQBrowser/10.2.2265.400',
        }
    
        async with aiohttp.ClientSession() as session:
            # 获取轮播图地址
            async with session.get(url,headers=headers) as response:
                try:
                    html = await response.text()   # 获取到网页源码
                    print(html)
                    
                except Exception as e:
                    print("基本错误")
                    print(e)
    
    # 这部分你可以直接临摹
    loop = asyncio.get_event_loop()
    tasks = asyncio.ensure_future(fetch_img_url(1))
    results = loop.run_until_complete(tasks)
    
    
    

    上面代码最后一部分也可以写成

    loop = asyncio.get_event_loop()
    tasks =  [fetch_img_url(1)]
    results = loop.run_until_complete(asyncio.wait(tasks))
    

    好了,如果你已经成果的获取到了源码,那么距离最终的目的就差那么一丢丢了。
    修改代码为批量获取10页。
    只需要修改tasks即可,在此运行,看到如下结果

    tasks =  [fetch_img_url(num) for num in range(1, 10)]
    

    在这里插入图片描述

    下面的一系列操作和上一篇博客非常类似,找规律。
    随便打开一个页面

    http://bbs.fengniao.com/forum/forum_101_4_lastpost.html
    

    点击一张图片,进入内页,在点击内页的一张图片,进入到一个轮播页面
    在这里插入图片描述

    再次点击进入图片播放页面

    在这里插入图片描述

    最后我们在图片播放页面,找到源码中发现了所有的图片链接,那么问题出来了,如何从上面的第一个链接,转变成轮播图的链接???
    下面的源码是在 http://bbs.fengniao.com/forum/pic/slide_101_10408464_89383854.html 右键查看源码。
    在这里插入图片描述

    继续分析吧~~~~ ヾ(=・ω・=)o

    http://bbs.fengniao.com/forum/forum_101_4_lastpost.html
    转变成下面的链接?
    http://bbs.fengniao.com/forum/pic/slide_101_10408464_89383854.html
    

    继续看第一个链接,我们使用F12开发者工具,去抓取一个图片看看。

    在这里插入图片描述

    图片中标黄色框的位置,发现了我们想要的数字,那么好了,我们只需要通过正则表达式把他们匹配出来就好了。
    代码在下面####的位置,需要注意的是,我采用的原始的正则匹配,在编写正则表达式的过程中,我发现一步竟然没有完整匹配,只能分成两个步骤了,你可以看一下具体的细节o(╥﹏╥)o

    1. 查找所有的图片<div class="picList">
    2. 获取我们想要的两部分数字
    async def fetch_img_url(num):
        url = f'http://bbs.fengniao.com/forum/forum_101_{num}_lastpost.html'
        print(url)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6726.400 QQBrowser/10.2.2265.400',
        }
    
        async with aiohttp.ClientSession() as session:
            # 获取轮播图地址
            async with session.get(url,headers=headers) as response:
                try:
                	###############################################
                    url_format = "http://bbs.fengniao.com/forum/pic/slide_101_{0}_{1}.html"
                    html = await response.text()   # 获取到网页源码
                    pattern = re.compile('<div class="picList">([sS.]*?)</div>')
                    first_match = pattern.findall(html)
                    href_pattern = re.compile('href="/forum/(d+?)_p(d+?).html')
                    urls = [url_format.format(href_pattern.search(url).group(1), href_pattern.search(url).group(2)) for url in first_match]
                    ##############################################
    
                except Exception as e:
                    print("基本错误")
                    print(e)
    
    

    代码完成,我们已经获取到,我们想要的URL了,下面继续读取URL内部信息,然后匹配我们想要的图片链接

    async def fetch_img_url(num):
        # 去抄上面的代码
        async with aiohttp.ClientSession() as session:
            # 获取轮播图地址
            async with session.get(url,headers=headers) as response:
                try:
                    #去抄上面的代码去吧
                    ################################################################
                    for img_slider in urls:
                        try:
                            async with session.get(img_slider, headers=headers) as slider:
                                slider_html = await slider.text()   # 获取到网页源码
                                try:
                                    pic_list_pattern = re.compile('var picList = [(.*)?];')
                                    pic_list = "[{}]".format(pic_list_pattern.search(slider_html).group(1))
                                    pic_json = json.loads(pic_list)  # 图片列表已经拿到
                                    print(pic_json)
                                except Exception as e:
                                    print("代码调试错误")
                                    print(pic_list)
                                    print("*"*100)
                                    print(e)
    
                        except Exception as e:
                            print("获取图片列表错误")
                            print(img_slider)
                            print(e)
                            continue
    				################################################################
    
    
                    print("{}已经操作完毕".format(url))
                except Exception as e:
                    print("基本错误")
                    print(e)
    

    在这里插入图片描述

    图片最终的JSON已经拿到,最后一步,下载图片,当当当~~~~,一顿迅猛的操作之后,图片就拿下来了

    
    async def fetch_img_url(num):
        # 代码去上面找
        async with aiohttp.ClientSession() as session:
            # 获取轮播图地址
            async with session.get(url,headers=headers) as response:
                try:
                    # 代码去上面找
                    for img_slider in urls:
                        try:
                            async with session.get(img_slider, headers=headers) as slider:
                                # 代码去上面找
    							##########################################################
                                for img in pic_json:
                                    try:
                                        img = img["downloadPic"]
                                        async with session.get(img, headers=headers) as img_res:
                                            imgcode = await img_res.read()  # 图片读取
                                            with open("images/{}".format(img.split('/')[-1]), 'wb') as f:
                                                f.write(imgcode)
                                                f.close()
                                    except Exception as e:
                                        print("图片下载错误")
                                        print(e)
                                        continue
                                ###############################################################
    
                        except Exception as e:
                            print("获取图片列表错误")
                            print(img_slider)
                            print(e)
                            continue
                    print("{}已经操作完毕".format(url))
                except Exception as e:
                    print("基本错误")
                    print(e)
    
    

    图片会在你提前写好的images文件夹里面快速的生成
    在这里插入图片描述

    tasks最多可以开1024协程,但是建议你开100个就OK了,太多并发,人家服务器吃不消。

    以上操作执行完毕,在添加一些细节,比如保存到指定文件夹,就OK了。

    github代码地址

  • 相关阅读:
    收藏夹
    获取某个元素在页面上的偏移量
    React多行文本溢出处理(仅针对纯文本)
    react
    CDN初学搭建(ats)
    linux查看cpu、内存、版本信息
    MySQL5.6版本性能调优my.cnf详解
    How to install cacti on centos 6
    win10安装.net3.5 报错解决
    CentOS6.5安装Cacti统计图乱码解决
  • 原文地址:https://www.cnblogs.com/happymeng/p/10141143.html
Copyright © 2020-2023  润新知