上一篇博文介绍了如何用selenium+python在诸如soso、谷歌、好搜等搜索引擎上爬取图片的方法,但是却没用提到百度,因为百度的情况比较特殊。首先,百度图片的数据更好,因为每幅图片都有“data-desc”描述可以作为图像很好的语义标签,此外基于百度较强的技术其查询搜索得到的图片相关性较高,后续人工筛选工作较少;其次,百度图片的数据不容易爬取,如果像前一篇文章中的方法取img标签的src值作为下载url,是下载不到图片的,得到的知识167B的非图像数据。
那么,如何爬取百度图片呢,笔者尝试了两种方法。第一种方法尚未完整实现,但思路已完整,第二种方法可以较为简单的爬到百度图片数据源。下面依次介绍两种实现方案。
方案1:
使用selenium模拟鼠标操作--“将鼠标放置图像上方,右键并选择图像另存为选项”,然后就可以保存了,代码如下:
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys # init url = 'http://image.baidu.com/i?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E6%89%8B%E6%9C%BA&oq=shouji&rsp=1' xpath = '//ul/li/div/a/img' # set profile fp = webdriver.FirefoxProfile() fp.set_preference('browser.download.folderList', 2) fp.set_preference('browser.download.manager.showWhenStarting', False) fp.set_preference('browser.download.dir', './yourfolder/') fp.set_preference('browser.helperApps.neverAsk.saveToDisk', 'image/jpeg') # launch driver driver = webdriver.Firefox(firefox_profile=fp) driver.maximize_window() driver.get(url) for element in driver.find_elements_by_xpath(xpath): img_url = element.get_attribute('src') img_desc = element.get_attribute('data-desc') action = ActionChains(driver).move_to_element(element) action.context_click(element) action.send_keys(Keys.ARROW_DOWN) action.send_keys('v') action.perform() # click save image driver.close()但是,想必大家都会发现,保存图片还需要一次次点击对话框的确认保存,很繁琐。的确,为了解决这个问题,我google了好久并没有找到直接解决的好方法,根本原因是selenium无法操作操作系统级的对话框,有说上面“set profile”代码段的设置能解决问题的并不靠谱。所以,如果采用右键另存为的方案的话,需要额外使用插件或钩子程序模拟自动点击。网上有推荐一个AutoIT的或可完成任务,未亲试。
方案2:
百度图片img标签内含的src并不能下载到原图片,只有data-desc属性可用,但是,当鼠标放在百度图片上时,会发现如下图所示的下载按钮,
只要找到这个上面这个下载按钮对应的链接即可下载到原图,而按钮对应的则是一个a链接标签,分析出其xpath问题即解决了,下面给出python代码:
import urllib import time from selenium import webdriver class Crawler: def __init__(self): self.url = 'http://image.baidu.com/i?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=index&fr=&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E6%89%8B%E6%9C%BA&oq=shouji&rsp=1' # url to crawl self.img_xpath = '//ul/li/div/a/img' # xpath of img element self.download_xpath = '//ul/li/div/div/span/a[@class="downloadicon"]' # xpath of download link element self.img_url_dic = {} # kernel function def launch(self): # launch driver driver = webdriver.Firefox() driver.maximize_window() driver.get(self.url) img_xpath = self.img_xpath download_xpath = self.download_xpath img_url_dic = self.img_url_dic # 模拟滚动窗口以浏览下载更多图片 pos = 0 for i in range(10): pos += i*500 # 每次下滚500 js = "document.documentElement.scrollTop=%d" % pos driver.execute_script(js) # get image desc and download for img_element, link_element in zip(driver.find_elements_by_xpath(img_xpath), driver.find_elements_by_xpath(download_xpath)): img_desc = img_element.get_attribute('data-desc') # description of image img_desc = self.filter_filename_str(img_desc) img_url = link_element.get_attribute('href') # url of source image if img_url != None and not img_url_dic.has_key(img_url): img_url_dic[img_url] = '' ext = img_url.split('.')[-1] filename = img_desc + '.' + ext print img_desc, img_url urllib.urlretrieve(img_url, './yourfolder/%s' % filename) time.sleep(1) driver.close() # filter invalid characters in filename def filter_filename_str(self, s): invalid_set = ('\\','/',':','*','?','"','<','>','|',' ') for i in invalid_set: s = s.replace(i, '_') return s if __name__ == '__main__': crawler = Crawler() crawler.launch()爬取后的结果图如下所示:
以上代码仅示例的实现了方案,验证其可行性,内部可能含有部分疏漏,仅供需要的朋友参考,不妥之处请指正。
selenium+python 爬取网络图片(2) -- 百度
原文地址:http://blog.csdn.net/seanwang_25/article/details/43318907