作为一个斗图狂魔,怎么能在群聊的时候认怂。不服就干,今天来爬一堆表情包,用于群聊的时候斗图使用。斗疯一个算一个,尽显群聊斗神本色。源码开始:

"""
    用Python爬取斗图表情包
    目标网址:https://www.xxx.com/的斗图表情包
"""

import requests
from bs4 import BeautifulSoup #解析网页用的
import os #用以存储文件的时候用的
import random

#首先获取网页内容
def get_html_content(url):
    #定义一堆User-Agent(正常的)
    simpleUA = [
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14'
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0'
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 OPR/76.0.4017.94 (Edition utorrent)'
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.46'
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.0.0 Safari/537.36'
        'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
    ]
    myUserAgent = random.choice(simpleUA) #随机选择就好
    headers = {
        'User-Agent': myUserAgent,
    }

    #开始请求网页
    r = requests.get(url, headers=headers)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    r.encoding = 'utf-8' #处理编码的
    content = r.text #返回的内容

    return content

def parse_page(htmlContent):
    """
    解析网页内容
    :param htmlContent:
    :return:
    """
    web_content = BeautifulSoup(htmlContent, 'lxml')
    image_lists = web_content.findAll('img') #找到网页中所有的img标签
    #将image_lists强制转换为列表类型,要不然它是bs4啥的啥的
    image_lists = list(image_lists) #获取网页中所有的图片,当然也包括网站的logo,这个logo不是我们想要的

    return image_lists

def get_image_names(image_lists):
    image_names = [] #空列表以存储解析出来的图片名称
    #我们这里的image_lists是包含logo的,所以我们要切片把它剔除
    for i in image_lists[1:-1]: #遍历列表的第二项到最后一项
        #其中这个i是bs4啥的,我们要强制转换成str类型方便操作
        # print(i) #<img alt="问候沙雕网友是否吃饭_表情包图片" data-v-39bd7a82=""
        afind = str(i).find('"') #找到字符串中的第一个双引号
        bfind = str(i).find('_') #找到字符串中的第一个下划线
        image_name = str(i)[afind+1:bfind] #中间的部分就是我们要的图片名称
        image_names.append(image_name)
    print(image_names) #用于查看和new_image_lists的前后区别
    #这里还会存在一个问题就是,windows的标题名称是支持?中文的,但是不支持西文的,所以还得处理下标题里出现的西文符号
    new_image_lists = [str(image_name).replace('?','?').replace('/', '反斜杠在此') for image_name in image_names]

    return new_image_lists

def get_image_urls(image_lists):
    image_urls = [] #这里提取url只是方便下载图片
    for i in image_lists[1:-1]: #处理方法跟取回文件名称一样
        # print(i)
        # 查找字符串中的https之前的项目
        afind = str(i).find('"h')
        # 再查找字符串的末尾url之前的"/
        bfind = str(i).find('"/')
        # afind和bfind之间的就是我们需要的url
        image_url = str(i)[afind + 1:bfind]  # 切片是包前不包后
        # print(image_url) #打印看是否符合预期
        image_urls.append(image_url)  # 因为是逐项添加,所以不需要担心顺序的问题

    return image_urls

#如果怕出错,可以先操作一页
if __name__ == '__main__':
    url = 'https://www.xxx.com/img_lists/new/1'
    content = get_html_content(url) #解析网页
    image_lists = parse_page(content) #解析网页后得到的图片信息列表
    image_names = get_image_names(image_lists) #图片名列表
    image_urls = get_image_urls(image_lists) #图片url列表
    # print(get_image_names(image_lists)) 打印一下,对比一下image_names和new_image_names
    all_data = zip(image_names, image_urls)
    filePath = 'images' #当前文件文件夹下的images目录,我们要存储图片的目录
    for image_name, image_url in all_data:
        if os.path.exists(filePath):
            #开始请求图片地址
            rimg = requests.get(image_url) #这里就不用headers了,有些网站需要用的,不然请求不到信息
            rimg.raise_for_status()
            # houzhui = image_url.split('.')[1]
            # print(houzhui)
            #开始以我们获取的文件名和处理的文件后缀进行图片存储
            with open(os.path.join(filePath, image_name + '.' + image_url.split('.')[-1]), 'wb') as f:
                #这里我们是直接写入文件夹,所以要用到os.path.join,image_name就是文件名,.就是图片格式的.,image_url.split就是以.拆分并取最后一部分.
                f.write(rimg.content) #写入文件
                f.close() #关闭文件

#我们这里只扫一页,如果要全部扫下来,就在url前面加个for循环。
# for page in range(1, 34):
#     url = f'https://www.xxx.com/img_lists/new/{page}'z最终

最终效果,爬了几千:

群聊斗神 - Python爬取斗图表情包 - 斗图之神的战斗神_文件名

 

从此再也不怕群聊斗图了,放马过来。。

 

代码有几点说明下,以供斗神复习:

      1,关于windows能存储文件格式名的问题,它不能包含特殊字符(也就是有些字符,比如说西文?,注意是西文的,不是中文的),所以在处理文件名的时候,要将这个处理掉。上面代码个人总结了三种方法处理。

      • 第一种是,直接从get_image_name函数里直接处理,用表达式处理;
      • 第二种是,在提取到了文件后开始写入之前,也就是在for image_name, image_url in all_data:做一段代码如if,re.sub()来处理;
      • 第三种类似第二种,就是提取提取出来了文件名后,写一个函数专门处理,然后函数再返回给代码就行了。可以说是工厂模式么?

      2,一般with open都是打开文件,而不是文件夹,所以这里用了os.path
      3,就是字符串的切片了,无所不能,哈哈
      4,要找下BeautifulSoup的资料。