当前位置:   article > 正文

python按关键字爬取必应高清图片_基于关键词 搜索合适的图片

基于关键词 搜索合适的图片

通过查询前人的博客,发现必应可通过url按关键字查找图片:

https://www.bing.com/images/async?q=查询关键字&first=图片编号&count=图片数量&mmasync=1

 

基于该url,我写了一个爬虫类,实现了按关键字下载固定数量的必应高清图片。调用时只需要一条python语句即可(由于使用了线程池并发请求图片,所以下载速度较快,一分钟300张高清图片没问题):

  1. # 关键词:电脑壁纸
  2. # 需要的图片数量:100
  3. # 图片保存路径:'E:\images'
  4. BingImagesSpider('电脑美女壁纸', 100, 'E:\images').run()

 

爬虫类的源码如下:

  1. import requests
  2. from lxml import etree
  3. import os
  4. from multiprocessing.dummy import Pool
  5. import json
  6. from time import time
  7. # 作用:按关键字、图片数量爬取必应图片,存放到指定路径。
  8. # 使用方法:只需运行一条命令 BingImagesSpider('电脑美女壁纸', 200, 'E:\images').run()
  9. class BingImagesSpider:
  10. thread_amount = 1000 # 线程池数量,线程池用于多IO请求,减少总的http请求时间
  11. per_page_images = 30 # 每页必应请求的图片数
  12. count = 0 # 图片计数
  13. success_count = 0
  14. # 忽略图片标签的一些字符
  15. ignore_chars = ['|', '.', ',', ',', '', '', '/', '@', ':', ':', ';', ';', '[', ']', '+']
  16. # 允许的图片类型
  17. image_types = ['bmp', 'jpg', 'png', 'tif', 'gif', 'pcx', 'tga', 'exif', 'fpx', 'svg', 'psd', 'cdr', 'pcd', 'dxf', 'ufo', 'eps', 'ai', 'raw', 'WMF', 'webp']
  18. # 请求头
  19. headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'}
  20. # 必应图片 url
  21. bing_image_url_pattern = 'https://www.bing.com/images/async?q={}&first={}&count={}&mmasync=1'
  22. def __init__(self, keyword, amount, path='./'):
  23. # keyword: 需爬取的关键字
  24. # amount: 需爬取的数量
  25. # path: 图片存放路径
  26. self.keyword = keyword
  27. self.amount = amount
  28. self.path = path
  29. self.thread_pool = Pool(self.thread_amount)
  30. def __del__(self):
  31. self.thread_pool.close()
  32. self.thread_pool.join()
  33. # 作用:从必应请求图片
  34. def request_homepage(self, url):
  35. # url: 必应图片页的 url
  36. return requests.get(url, headers=self.headers)
  37. # 作用:解析必应网页,得到所有图片的信息,封装到列表中返回
  38. # 每个图片的信息以字典对象存储,字典的键包括 image_title, image_type, image_md5, image_url
  39. def parse_homepage_response(self, response):
  40. # response: 必应网站的响应
  41. # 获取各图片信息所在的json格式字符串 m
  42. tree = etree.HTML(response.text)
  43. m_list = tree.xpath('//*[@class="imgpt"]/a/@m')
  44. # 对每个图片分别处理
  45. info_list = []
  46. for m in m_list:
  47. dic = json.loads(m)
  48. # 去除一些文件名中不允许的字符
  49. image_title = dic['t']
  50. for char in self.ignore_chars:
  51. image_title = image_title.replace(char, ' ')
  52. image_title = image_title.strip()
  53. # 有些图片的信息中不包含图片格式,该情况将图片设置为 jpg 格式
  54. image_type = dic['murl'].split('.')[-1]
  55. if image_type not in self.image_types:
  56. image_type = 'jpg'
  57. # 将每个图片的信息存为字典格式
  58. info = dict()
  59. info['image_title'] = image_title
  60. info['image_type'] = image_type
  61. info['image_md5'] = dic['md5']
  62. info['image_url'] = dic['murl']
  63. info_list.append(info)
  64. return info_list
  65. # 请求具体图片,保存到初始化时指定的路径
  66. def request_and_save_image(self, info):
  67. # info: 每个图片的信息,以字典对象存储。字典的键包括 image_title, image_type, image_md5, image_url
  68. filename = '{} {}.{}'.format(self.count, info['image_title'], info['image_type'])
  69. filepath = os.path.join(self.path, filename)
  70. try:
  71. # 请求图片
  72. response = requests.get(info['image_url'], headers=self.headers, timeout=1.5)
  73. # 保存图片
  74. with open(filepath, 'wb') as fp:
  75. fp.write(response.content)
  76. # 打印日志
  77. self.count += 1
  78. self.success_count += 1
  79. print('{}: saving {} done.'.format(self.count, filepath))
  80. except requests.exceptions.RequestException as e:
  81. self.count += 1
  82. print('{}: saving {}failed. url: {}'.format(self.count, filepath, info['image_url']))
  83. print('\t tip:', e)
  84. # 作用:图片信息的列表去重,去除重复的图片信息
  85. def deduplication(self, info_list):
  86. result = []
  87. # 用图片的 md5 做为唯一标识符
  88. md5_set = set()
  89. for info in info_list:
  90. if info['image_md5'] not in md5_set:
  91. result.append(info)
  92. md5_set.add(info['image_md5'])
  93. return result
  94. # 作用:运行爬虫,爬取图片
  95. def run(self):
  96. # 创建用于保存图片的目录
  97. if not os.path.exists(self.path):
  98. os.mkdir(self.path)
  99. # 根据关键词和需要的图片数量,生成将爬取的必应图片网页列表
  100. homepage_urls = []
  101. for i in range(int(self.amount/self.per_page_images * 1.5) + 1): # 由于有些图片会重复,故先请求1.5倍图片,豁免
  102. url = self.bing_image_url_pattern.format(self.keyword, i*self.per_page_images, self.per_page_images)
  103. homepage_urls.append(url)
  104. print('homepage_urls len {}'.format(len(homepage_urls)))
  105. # 通过线程池请求所有必应图片网页
  106. homepage_responses = self.thread_pool.map(self.request_homepage, homepage_urls)
  107. # 从必应网页解析所有图片的信息,每个图片包括 image_title, image_type, image_md5, image_url 等信息。
  108. info_list = []
  109. for response in homepage_responses:
  110. result = self.parse_homepage_response(response)
  111. info_list += result
  112. print('info amount before deduplication', len(info_list))
  113. # 删除重复的图片,避免重复下载
  114. info_list = self.deduplication(info_list)
  115. print('info amount after deduplication', len(info_list))
  116. info_list = info_list[ : self.amount]
  117. print('info amount after split', len(info_list))
  118. # 下载所有图片,并保存
  119. self.thread_pool.map(self.request_and_save_image, info_list)
  120. print('all done. {} successfully downloaded, {} failed.'.format(self.success_count, self.count - self.success_count))
  121. if __name__ == '__main__':
  122. # 关键词:电脑壁纸
  123. # 需要的图片数量:100
  124. # 图片保存路径:'E:\images'
  125. start = time()
  126. BingImagesSpider('电脑壁纸', 100, 'E:\images').run()
  127. print(time() - start)

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/312047
推荐阅读
相关标签
  

闽ICP备14008679号