selenium+python 爬取网络图片(2) -- 百度,,上一篇博文介绍了如何


上一篇博文介绍了如何用selenium+python在诸如soso、谷歌、好搜等搜索引擎上爬取图片的方法,但是却没用提到百度,因为百度的情况比较特殊。首先,百度图片的数据更好,因为每幅图片都有“data-desc”描述可以作为图像很好的语义标签,此外基于百度较强的技术其查询搜索得到的图片相关性较高,后续人工筛选工作较少;其次,百度图片的数据不容易爬取,如果像前一篇文章中的方法取img标签的src值作为下载url,是下载不到图片的,得到的知识167B的非图像数据。


那么,如何爬取百度图片呢,笔者尝试了两种方法。第一种方法尚未完整实现,但思路已完整,第二种方法可以较为简单的爬到百度图片数据源。下面依次介绍两种实现方案。


方案1:

使用selenium模拟鼠标操作--“将鼠标放置图像上方,右键并选择图像另存为选项”,然后就可以保存了,代码如下:

from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.common.keys import Keys# initurl = '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 profilefp = 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 driverdriver = 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 imagedriver.close()
但是,想必大家都会发现,保存图片还需要一次次点击对话框的确认保存,很繁琐。的确,为了解决这个问题,我google了好久并没有找到直接解决的好方法,根本原因是selenium无法操作操作系统级的对话框,有说上面“set profile”代码段的设置能解决问题的并不靠谱。所以,如果采用右键另存为的方案的话,需要额外使用插件或钩子程序模拟自动点击。网上有推荐一个AutoIT的或可完成任务,未亲试。


方案2:

百度图片img标签内含的src并不能下载到原图片,只有data-desc属性可用,但是,当鼠标放在百度图片上时,会发现如下图所示的下载按钮,

技术分享

只要找到这个上面这个下载按钮对应的链接即可下载到原图,而按钮对应的则是一个a链接标签,分析出其xpath问题即解决了,下面给出python代码:

import urllibimport timefrom selenium import webdriverclass 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) -- 百度

评论关闭