zoukankan      html  css  js  c++  java
  • 爬虫一个图片网站

    这次爬取一点有意思的东西,爬一个美女网站

    1.爬取目标

    本次爬虫比较简单,先只爬取网站中的“大胸妹”tab,而且只爬取最外层的图片,不点开图集,如

    2.分析网页元素

    网页源码如下

    可以看到很明显的规律,每个图片都包裹在<img>标签中,而且title属性代表名称,src属性代表图片url

    所以本次爬虫就提取上述2个元素:alt和src

    可以用BeautifulSoup或者正则表达式进行提取

    3.爬取过程

    先贴出完整代码,再进行分析

    # -*- coding:utf-8 -*-
    import requests
    from requests.exceptions import RequestException
    from bs4 import BeautifulSoup
    import bs4
    import os
    
    
    def get_html(url, header=None):
        """请求初始url"""
        response = requests.get(url, headers=header)
        try:
            if response.status_code == 200:
                # print(response.status_code)
                # print(response.text)
                return response.text
            return None
        except RequestException:
            print("请求失败")
            return None
    
    
    def parse_html(html, list_data):
        """提取img的名称和图片url,并将名称和图片地址以字典形式返回"""
        soup = BeautifulSoup(html, 'html.parser')
        img = soup.find_all('img')
        for t in img:
            if isinstance(t, bs4.element.Tag):
                # print(t)
                name = t.get('alt')
                img_src = t.get('src')
                list_data.append([name, img_src])
        dict_data = dict(list_data)
        return dict_data
    
    def get_image_content(url):
        """请求图片url,返回二进制内容"""
        print("正在下载", url)
        try:
            r = requests.get(url)
            if r.status_code == 200:
                return r.content
            return None
        except RequestException:
            return None
    
    
    def main(num=None, depth=None):
        base_url = 'https://www.dbmeinv.com/index.htm?'
        for i in range(1, depth):
            url = base_url + 'cid=' + str(num) + '&' + 'pager_offset=' + str(i)
            # print(url)
            header = {
                'Accept': 'text/html,application/xhtml+xml,application/xml;q = 0.9, image/webp,image/apng,*/*;q='
                          '0.8',
                'Accept-Encoding': 'gzip,deflate,br',
                'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                'Cache-Control': 'max-age=0',
                'Connection': 'keep-alive',
                'Host': 'www.dbmeinv.com',
                'Upgrade-Insecure-Requests': '1',
                'User-Agent': 'Mozilla/5.0(WindowsNT6.1;Win64;x64) AppleWebKit/537.36(KHTML, likeGecko) Chrome/'
                              '70.0.3538.102Safari/537.36 '
            }
            list_data = []
            html = get_html(url)
            # print(html)
            dictdata = parse_html(html, list_data)
            # print(list_data)
            # print(dict(list_data))
            # print(data)
            # for url in data.values():
            #     download_image(url)
            root_dir = os.path.dirname(os.path.abspath('.'))
            save_path = root_dir + '/pics/'
            for t in dictdata.items():
                file_path = '{0}/{1}.{2}'.format(save_path, t[0], 'jpg')
                if not os.path.exists(file_path):  # 判断是否存在文件,不存在则爬取
                    with open(file_path, 'wb') as f:
                        f.write(get_image_content(t[1]))
                        f.close()
                        print('文件保存成功')
    
    
    if __name__ == '__main__':
        # t = main(2)
        # print(t)  # 这样打印之所以为None,是因为main函数中没有任何内容返回出来,尴尬了。。。
        main(2, 10)

    (1)构造url

    “大胸妹”首页url为:https://www.buxiuse.com/?cid=2

    翻到下一页后,变为:https://www.buxiuse.com/?cid=2&page=2

    可以看到有2个参数cid和page

    所在在主函数中,定义了2个参数,一个表示“大胸妹”对应的cid值,一个表示翻页

    def main(num=None, depth=None):
        base_url = 'https://www.buxiuse.com/?'
        for i in range(1, depth):
            url = base_url + 'cid=' + str(num) + '&' + 'page=' + str(i)

    (2)分析parse_html()方法

    这个方法用来提取图片的title和src,使用的是BeautifulSoup;

    传入2个参数,一个是初始url的返回内容,另外定义了一个list_data这里表示一个列表,会把提取到的title和src,以[title:src]的形式追加到list_data中;

    然后再把list_data转换为字典返回出去,这样就得到了一个以title为键,以src为值的字典。

    后面可以通过迭代这个字典,在保存图片时,使用图片的title作为图片名称

    打印list_data和dict_data分别如下

     (3)根据parse_html()方法得到图片url后,还需要进一步请求图片url,并将返回的二进制内容以jpg的格式进行保存

    首先定义了一个get_image_content()方法,它与get_html()方法一样,不过是返回的二进制内容

    然后就是主函数中构造图片保存的形式了:

    因为parse_html()方法返回了dict_data,它是以title为键,以src为值的字典,

    我们知道迭代字典,可以得到一个键值对组成的元组,如下:

    所以可以通过迭代这个字典,分别提取字典的键作为图片名称,提取字典值作为图片url进行请求,如下:

    root_dir = os.path.dirname(os.path.abspath('.'))
    save_path = root_dir + '/pics/'
    for t in dictdata.items():
        file_path = '{0}/{1}.{2}'.format(save_path, t[0], 'jpg')
        if not os.path.exists(file_path):  # 判断是否存在文件,不存在则爬取
            with open(file_path, 'wb') as f:
                f.write(get_image_content(t[1]))
                f.close()
                print('文件保存成功')

    t[0]表示每个键值对的键,即图片的title;t[1]表示每个键值对的值,即图片的url

     最终保存的图片如下


    补充:用正则提取

    import re
    import requests
    import os
    from requests.exceptions import RequestException
    
    r = requests.get('https://www.buxiuse.com/?cid=2')
    # print(r.status_code)
    html = r.text
    # print(r.text)
    # print(html)
    
    name_pattern = re.compile(r'<img class="height_min".*?title="(.*?)"', re.S)
    src_pattern = re.compile(r'<img class="height_min".*?src="(.*?.jpg)"', re.S)
    
    name = name_pattern.findall(html)  # 提取title
    src = src_pattern.findall(html)  # 提取src
    data = [name,src]
    # print(name)
    # print(src)
    d=[]
    for i in range(len(name)):
        # print(name[i])
        # print(src[i])
        d.append([name[i], src[i]])
    
    dictdata = dict(d)
    for i in dictdata.items():
        print(i)
    
    def get_content(url):
        try:
            r = requests.get(url)
            if r.status_code == 200:
                return r.content
            return None
        except RequestException:
            return None
    
    
    root_dir = os.path.dirname(os.path.abspath('.'))
    save_path = root_dir + '/pics/'
    for t in dictdata.items():
        file_path = '{0}/{1}.{2}'.format(save_path, t[0], 'jpg')
        if not os.path.exists(file_path):  # 判断是否存在文件,不存在则爬取
            with open(file_path, 'wb') as f:
                f.write(get_content(t[1]))
                f.close()
                print('文件保存成功')
  • 相关阅读:
    linux系统中如何进入退出vim编辑器,方法及区别
    [转]JAVA的动态代理机制及Spring的实现方式
    mybaties 缓存
    全面分析 Spring 的编程式事务管理及声明式事务管理
    面试(4)-spring-Spring面试题和答案
    vector的多套遍历方案
    【QT】QT下载与安装
    【QT】无需写connect代码关联信号和槽函数
    【QT】第一个QT程序(点击按钮,显示特定文本)
    【QT】error: 'SIGNAL' was not declared in this scope
  • 原文地址:https://www.cnblogs.com/hanmk/p/10024520.html
Copyright © 2011-2022 走看看