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