码农吸猫必备,【几行代码】就能采集万张猫咪图

2022-09-22 15:23:13 浏览数 (3)

“作为一个 Python 爬虫爱好者,当看到涉及猫咪活动的时候,首先想到的就是采集猫咪图,那我们就实现一款猫咪图采集器吧。 ”

目标站点说明

本次要采集的站点为:,该网站提供了丰富的图片资源,这些内容都可以分类采集,本文仅采集与 “猫咪” 相关的素材。

本案例用到的技术模块

  • requests:负责请求发送;- lxml:负责数据提取。目标站点分析 列表页分页规则如下所示:
代码语言:javascript复制
https://www.tooopen.com/img/89_869_1_1.aspx
https://www.tooopen.com/img/89_869_1_2.aspx
https://www.tooopen.com/img/89_869_1_{页码}.aspx

通过开发者工具查阅页面元素时,发现页面有 JS 动态加载而成,在 DOM 结构中存在如下代码(下图红框区域),这部分数据为 JSON 格式,在后续的编码过程中,可以直接进行序列化操作。

获取猫咪大图

由于列表页展示的是猫咪缩略图,所以需要进入详情页提取分辨率更高的图片,这里采用两步编码,第一步提取详情页地址,第二步从详情页提取大图地址。

拿 举例,该部分标签中存 id=Detail-MaterialID,既然标签存在 ID 值,那后续的提取就变的简单了许多。

编码时间

首先封装一个通用的请求函数,原因是存在 3 次请求的发送:

  1. 请求列表页,获取详情页地址;1. 请求详情页,获取猫咪大图地址;1. 请求猫咪大图,获取图片数据(不过最后一步,没有写到该函数中进行判断)
代码语言:javascript复制
# 获取网页响应内容
def common_requests(url):
    try:
        res = requests.get(url=url, headers=headers, timeout=3)
        html_str = res.text
        # format_html(html_str)
        return html_str
    except Exception as e:
        print(e)
        return None

公用请求函数编写完毕之后,就可以编写核心逻辑部分,这部分代码由 2 部分构成:

  1. 获取网页响应源码;1. 解析网页源码,提取详情页地址。
代码语言:javascript复制
def get_html(url):
    # 列表页响应的源码
    ret_html = common_requests(url)
    if ret_html is not None:
        format_html(html=ret_html)


def format_html(html):
    element = etree.HTML(html)
    # 得到详情页地址
    img_name = element.xpath('//a[@class="pic"]/@title')
    detail_links = element.xpath('//a[@class="pic"]/@href')
    name_links = list(zip(img_name, detail_links))

    data_more_str = element.xpath('//div[@id="data-more"]/text()')[0]
    # 获取更多图片
    data_more = json.loads(data_more_str)

    if len(data_more) > 0:
        name_links.extend([(_['title'], _["url"]) for _ in data_more])

    if len(name_links) > 0:
        for name, link in name_links:

            # 详情页响应源码
            ret_detail_html = common_requests(link)
            if ret_detail_html is not None:
                get_big_img(name, ret_detail_html)

    else:
        pass

上述代码需要关注的是,提取本文开篇提及目标数据标签位置的代码,局部代码如下:

代码语言:javascript复制
element.xpath('//div[@id="data-more"]/text()')[0]

上述代码还调用了一个函数:get_big_img(),该函数目的是获取猫咪大图,函数体如下所示,可同步编写 save_img() 函数

代码语言:javascript复制
def get_big_img(name, ret_detail_html):
    element = etree.HTML(ret_detail_html)
    img_url = element.xpath('//img[@id="imgMainView"]/@src')
    if len(img_url) > 0:
        save_img(name, img_url[0])
    else:
        pass


# 保存图片
def save_img(name, img_url):
    img_headers = {<!-- -->
        "Host": "img08.tooopen.com",
        "Referer": "https://www.tooopen.com/view/2298460.html"
    }
    res = requests.get(url=img_url, headers=img_headers, timeout=10)
    data = res.content
    if data is not None:
        with open(f'./imgs/{<!-- -->name}.jpg', 'wb ') as f:
            f.write(data)

在请求图片地址时,由于其存在外链限制,所以需要在请求头中增加 HOSTReferer 参数。

最后在增加 main() 函数,实现对上述代码的调用,即可完成本案例。

代码语言:javascript复制
if __name__ == '__main__':
    headers = {<!-- -->
        "user-agent": 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0'
    }
    base_url = 'https://www.tooopen.com/img/89_869_1_{}.aspx'
    urls = [base_url.format(_) for _ in range(1, 100)]
    for url in urls:
        get_html(url)

运行代码之后,就会得到高清猫咪图,(由于目标站点不属于自己,可能存在版权问题,顾采集之后的图片及时删除)

1 人点赞