多线程爬虫——爬取Bing画廊

    xiaoxiao2025-04-29  10

    http://www.bing.com/gallery/ 里搜集了Bing首页的近5年的壁纸大图,大部分是1920x1200的。

    右侧就是Bing的壁纸,大多数是1920x1200的大图,少部分没有大图。

    对这个网站的爬取有一点难度。这个页面用js语句锁死了右侧图片栏的右键菜单,所以只能通过左侧打开chrome的元素菜单,然后再取得图片缩略图的地址。

    图片缩略图的地址通常为一串以640x320.jpg或320x180.jpg结尾的url,点击图片后可以点击右下角的下载按钮,从而找到大图的真实地址,即将缩略图中地址的“640x320“或”320x180”换成“1920x1200”即可,一个简单的字符串替换即可。

    然后……爬虫三件套出场:python+selenium+phantomjs/chromedriver,首先使用selenium检查出缩略图的图片元素,再提取出src属性值,得到缩略图地址;将缩略图地址进行字符串替换,得到真实的壁纸地址,最后把这些图片都下回来就好。

    该网站的图片采用动态加载,因此在程序中还需要使用js语句控制滚动条的下拉操作,待缩略图加载完成后,再取得地址。

    源代码如下:

    # -*- coding=utf-8 -*- from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver import ActionChains from selenium.common.exceptions import TimeoutException from selenium.webdriver.support import expected_conditions as EC import time,sys,re,urllib2,urllib,cookielib,datetime,requests import threading CHROMEDRIVER_PATH='D:\\WebDrivers\\chromedriver_win32\\chromedriver.exe' PHANTOMJS_PATH='D:\\WebDrivers\\phantomjs\\bin\\phantomjs.exe' class BingWorm: url="" driver=None pictures=[] dates=[] url_list=[] sub_url_list=[] threads=[] thread_count=1 def __init__(self): self.url="http://www.bing.com/gallery/" self.driver=webdriver.PhantomJS(executable_path=PHANTOMJS_PATH) #self.driver=webdriver.Chrome(executable_path=CHROMEDRIVER_PATH) def GetTodayPicture(self): pic_url="http://cn.bing.com/" wb_data=requests.get(pic_url) pic_pattern=re.compile(r'http://.*?bing\..*?1080.jpg') pic_address=pic_pattern.search(wb_data.text).group() filename_pattern=re.compile(r'rb/.*?\.jpg') filename=filename_pattern.search(pic_address).group()[4:] urllib.urlretrieve(pic_address,'D:\\TestData\\BingToday\\'+str(filename)) print "今日图片下载完成。" def GetPictures(self):#获取图片地址 self.driver.get(self.url) js = "document.body.scrollTop=document.body.scrollHeight" for i in range(0,10): self.driver.execute_script(js) time.sleep(1) time.sleep(3) self.pictures=self.driver.find_elements_by_class_name("tileBg") print "请稍后……" for picture in self.pictures: urls=str(picture.get_attribute("src")).replace("640x360","1920x1200").replace("320x180", "1920x1200") self.url_list.append(urls) self.driver.close() def TaskArrange(self,n):#n为线程数 self.thread_count=n task_list_count=len(self.url_list)/self.thread_count for i in range(0,len(self.url_list),task_list_count): self.sub_url_list.append(self.url_list[i:i+task_list_count]) #print self.sub_url_list def DownLoadPic(self,piclist): for picurl in piclist: filename_pattern=re.compile(r'files/.*?\.jpg') picname=filename_pattern.search(picurl).group()[6:] urllib.urlretrieve(picurl,"D:\\TestData\\Bing\\"+str(picname)+".jpg") print str(picname)+"下载完成。" def DownLoad(self): for i in range(0,len(self.sub_url_list)): self.threads.append(threading.Thread(target=self.DownLoadPic,args=(self.sub_url_list[i],))) for t in self.threads: t.start() if __name__=="__main__": worm=BingWorm() #worm.GetTodayPicture() worm.GetPictures() worm.TaskArrange(10) worm.DownLoad() exit() 其中,GetTodayPicture函数可以单独使用,单独从Bing首页上获得当天的壁纸。与Bing/Gallery网站上的壁纸相比,首页壁纸的最大特点就是没有Bing的水印。

    其中,GetPictures函数将取得的大图地址全部放在url_list中,以便TaskArrange函数将其切割成线程的任务list。TaskArrange函数将url_list根据线程数平均切割,将切割结果存储于sub_url_list中,这样sub_url_list为包含有list的list,在其中存储了每个线程的任务url;DownLoadPic(list)函数意为将list中的所有图片全部下回来。因此,在DownLoad中可以根据sub_url_list建立线程,让每个线程分别去下载sub_url_list的子list的图片,最终将图片下载回来。

    在循环下拉滚动条10次后,得到的图片结果如图所示:

    总文件数330,实际有图片的285,数据完好率85%。

    转载请注明原文地址: https://ju.6miu.com/read-1298565.html
    最新回复(0)