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

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%。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值