为了逗女朋友开心,想找一堆表情包,那么作为一名程序员,自然是会想到用程序来完成这个事情,而Python爬虫就是一个非常好的方法。
我先找到了一个专门发布表情包的网站,就叫做
分析站点
为了不引起不适,我选择搜索“你好”,出来的结果是这样的
可以看到共有688个相关的表情,右侧的表情包是分组形式的,不是我的爬取对象。我们只关注表情,在网页底部可以看到分页信息:
切换分页到第4页后,可以看到网址的编号情况如下:
keyword 后接关键词,此处为“你好”
type 后接类型,此处为"bq",对应表情
page 后接页码,此处为"4.html",对应第4页
到此就确定了关键词和分页信息的整合方式,根据这个可以按顺序获取指定关键词的所有分页。那么接下来的问题是如何解析每个分页中的图片信息,下面请看:
每个图片都在一个div标签内,使用chrome的调试工具可以获取到图片元素的xpath路径,然后稍作修改就可以匹配到当前页的所有图片
imgs = page.xpath('//div[@class="searchbqppdiv tagbqppdiv"]//img/@data-original')
好了,到此,网站的分页已经每页的图片获取方式都知道了,下面开始完成代码的编写↓
爬虫的代码实现获取指定关键词的所有分页
从分页中获取所有表情图片的链接
下载图片并存储到本地
get_imgs
首先对单个关键词,实现分页和图片链接的获取
def get_imgs(keyword):
'''爬取某一个关键词相关的所有表情包Args:keyword: 表情包关键词'''
page_index = 0
img_cnts = 0
save_dir = get_path(keyword)
while True:
page_index = page_index + 1
# https://fabiaoqing.com/search/search/keyword/抱抱/type/bq/page/1.html
url = '{}{}/type/bq/page/{}.html'.format(base_url, keyword, page_index)
response = requests.get(url, headers=headers).content
page = html.fromstring(response)
imgs = page.xpath(
'//div[@class="searchbqppdiv tagbqppdiv"]//img/@data-original')
print('爬取 "{}" 相关表情包第 {} 页:'.format(keyword, page_index))
img_cnts = download_imgs(imgs, img_cnts, save_dir)
if page_index == 1:
page_num = int(
page.xpath('//*[@id="mobilepage"]/text()')[0].split()[-1])
if page_index == page_num:
break
return img_cnts, save_dir
思路很简单,就是从1不断增加分页页码page_index,然后使用lxml中的xpath解析网页得到图片链接,最后使用下面介绍的download_imgs函数下载图片。那么什么时候停止获取呢?就是比较首页获取的总分页数page_num和当前分页数page_index是否一致,如果一致说明已经到最后一页。
函数中的get_path是个获取本地存储链接的函数,base_url和headers是两个全局变量
base_url = 'https://fabiaoqing.com/search/search/keyword/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36'
}
def get_path(keyword):
'''生成指定关键词对应的表情包存储路径'''
home_path = os.path.expanduser('~')
path = os.path.join(home_path, 'Pictures/python/表情包/' + keyword)
if not os.path.isdir(path):
os.makedirs(path)
return os.path.realpath(path)
download_imgs
def download_imgs(img_urls, starti, save_dir):
'''下载单个页面内所有图片Args:img_urls: 关键词相关表情包某一分页的所有图片链接starti: 当前页面首个图片命名idsave_dir: 图片存储路径'''
fid = starti
for img in img_urls:
print('\t' + img)
fid = fid + 1
file_name = '{}.{}'.format(fid, os.path.basename(img).split('.')[-1])
save_path = os.path.join(save_dir, file_name)
try:
with open(save_path, 'wb') as f:
f.write(requests.get(img, headers=headers, timeout=20).content)
except requests.exceptions.ConnectionError as ce:
print(ce.strerror())
except requests.exceptions.MissingSchema:
print(img + ' missing schema')
except requests.exceptions.ReadTimeout:
print('get {} timeout, skip this item.'.format(img))
finally:
pass
return fid
别看代码这么长,下载图片的关键就两行,和以往下载图片的方式大同小异,不再赘述。
with open(save_path, 'wb') as f:
f.write(requests.get(img, headers=headers, timeout=20).content)
main
主函数也比较简单,从命令行参数中获取所有关键词,逐个对关键词进行对应的表情爬取并统计爬取到的表情数。
def main():
if len(sys.argv) < 2:
usage()
sys.exit(0)
print('============================================')
for keyword in sys.argv[1:]:
print('开始爬取关键词为 "{}" 的表情包:'.format(keyword))
count, save_dir = get_imgs(keyword)
print('共爬取 "{}" 表情包 {} 个'.format(keyword, count))
print('文件存储于"{}"'.format(save_dir))
print('\n爬取完成!')
print('============================================')
由于我们的目的是根据输入的关键词参数获取相关的表情,代码完成后的使用方式是这样的:
python fabiaoqing_spider.py keyword1 keyword2 ...
所以usage函数是这样的,可以同时爬取多个关键词
def usage():
print('Usage:\n\t' + os.path.basename(sys.argv[0]) +
' [key1] [key2] [key3] ...\n')
爬取测试
python fabiaoqing_spider.py 你好 抱抱 亲亲
上面是截取的部分爬取过程,下面是亲亲表情包的爬取结果
代码已托管至Litreily/capturergithub.com