群聊斗神 - Python爬取斗图表情包 - 斗图之神的战斗神
作为一个斗图狂魔,怎么能在群聊的时候认怂。不服就干,今天来爬一堆表情包,用于群聊的时候斗图使用。斗疯一个算一个,尽显群聊斗神本色。源码开始:
""" 用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最终
最终效果,爬了几千:
从此再也不怕群聊斗图了,放马过来。。
代码有几点说明下,以供斗神复习:
1,关于windows能存储文件格式名的问题,它不能包含特殊字符(也就是有些字符,比如说西文?,注意是西文的,不是中文的),所以在处理文件名的时候,要将这个处理掉。上面代码个人总结了三种方法处理。
-
-
- 第一种是,直接从get_image_name函数里直接处理,用表达式处理;
- 第二种是,在提取到了文件后开始写入之前,也就是在for image_name, image_url in all_data:做一段代码如if,re.sub()来处理;
- 第三种类似第二种,就是提取提取出来了文件名后,写一个函数专门处理,然后函数再返回给代码就行了。可以说是工厂模式么?
-
2,一般with open都是打开文件,而不是文件夹,所以这里用了os.path
3,就是字符串的切片了,无所不能,哈哈
4,要找下BeautifulSoup的资料。