动态网页爬取图片——花瓣网

今天我们来爬取一个图片网站花瓣网,写一个比较简单的图片下载的爬虫;

迪丽热巴

图片太多了,只截了这些图片,大概几千张;
对,没错,就是你们喜欢的胖迪,
1、首先分析一下花瓣网图片的加载方式
打开花瓣网首页,搜索“迪丽热巴”,

第一页加载的20张图片

下拉加载出第二页的图片时弹出登录框,只有登录账号才可以继续加载后面的所有图片;


第二页加载的20张图片

可以看出,花瓣网的图片加载是异步加载的方式,这时我们可以选择selenium模拟登录网页模仿浏览器的操作不断的下拉加载出所有的图片;
2、主要思想:
首先要登录账号,输入要搜索的图片,每次下拉加载出当前页面的图片后,提取对于图片的url存到一个列表里,由于每页图片是20张,所以我这里在下载图片的时候也是每次存20个url就去下载对应的这20张图片;
3、准备工作:
安装selenium的库,pip或者下载到本地安装都OK;
下面是安装Phantomjs或者Chrome

chromedriver的安装路径
phantomjs的安装路径

具体下载可自行百度,或者参考下面的博客,这里感谢这位博主
在Windows下安装PIP+Phantomjs+Selenium
4、下面直接上代码

from selenium import webdriver
import time
import os
import requests


class Huaban():

    #获取图片url并存到列表urls_list
    def get_picture_url(self, content):
        global path
        path = "E:\spider\pictures\huaban" + '\\' + content
        # 保存图片到磁盘文件夹 file_path中,默认为当前脚本运行目录下的文件夹
        if not os.path.exists(path):
            os.makedirs(path)
        url = "http://huaban.com"
        # 使用Chrome浏览器模拟打开网页,但是要把下载的chromedriver.exe放在python的文件路径下,
        # 调试好之后换成PhantomJs,速度应该会快一点
        # driver = webdriver.PhantomJs()
        # 下拉滑动浏览器屏幕,具体下拉多少根据自己实际情况决定
        driver = webdriver.PhantomJS()
        #driver = webdriver.Chrome()
        # 设置全屏
        driver.maximize_window()
        driver.get(url)
        time.sleep(8)

        # 点击登录、呼起登录窗口
        driver.find_elements_by_xpath('//a[@class="login btn wbtn"]')[0].click()
        # sign in the username
        try:
            driver.find_elements_by_xpath('//input[@name="email"]')[0].send_keys('花瓣账号')
            print('user success!')
        except:
            print('user error!')
        time.sleep(3)
        # sign in the pasword
        try:
            driver.find_elements_by_xpath('//input[@name="password"]')[0].send_keys('账号密码')
            print('pw success!')
        except:
            print('pw error!')
        time.sleep(3)
        # click to login
        try:
            driver.find_elements_by_xpath('//a[@class="btn btn18 rbtn"]')[0].click()
            print('click success!')
        except:
            print('click error!')
        time.sleep(3)
        #搜索图片
        driver.find_elements_by_xpath('//input[@placeholder="搜索你喜欢的"]')[0].send_keys(content)
        driver.find_elements_by_xpath('//form[@id="search_form"]/a')[0].click()
        time.sleep(5)
        i = 0
        page = 1
        global name
        global store_path
        global urls_list
        urls_list = []
        #获取图片的总数
        pictures_count = driver.find_elements_by_xpath('//a[@class="selected"]/i')[0].text
        print(pictures_count)
        pages = int(int(pictures_count) / 20)
        print(pages)
        #匹配到图片url所在的元素
        url_elements = driver.find_elements_by_xpath('//span[@class="stop"]/../img')
        #遍历图片元素的列表获取图片的url
        for url_element in url_elements:
            picture_url = url_element.get_attribute("src")[:-3] + "658"
            #防止获取重复的图片url
            if picture_url not in urls_list:
                urls_list.append(picture_url)
        while page <= pages:
            while len(urls_list) < 20*page:
                driver.execute_script("window.scrollBy(0,1000)")
                time.sleep(3)
                url_elements = driver.find_elements_by_xpath('//span[@class="stop"]/../img')
                for url_element in url_elements:
                    picture_url = url_element.get_attribute("src")[:-3] + "658"
                    if picture_url not in urls_list:
                        urls_list.append(picture_url)
            print("第%s页" % page)

            for download_url in urls_list[20*(page-1):20*page]:
                i += 1
                name = content + "_" + str(i)
                store_path = name + '.jpg'
                self.store(download_url)
            page += 1
        #最后一页
        print("第%s页" % int(page))

        while len(urls_list) < int(pictures_count):
            driver.execute_script("window.scrollBy(0,1000)")
            time.sleep(3)
            url_elements = driver.find_elements_by_xpath('//span[@class="stop"]/../img')
            for url_element in url_elements:
                picture_url = url_element.get_attribute("src")[:-3] + "658"
                if picture_url not in urls_list:
                    urls_list.append(picture_url)
        for download_url in urls_list[20*(page-1): ]:
            i += 1
            name = content + "_" + str(i)
            store_path = name + '.jpg'
            self.store(download_url)
    #存储图片到本地
    def store(self, picture_url):
        picture = requests.get(picture_url)
        f = open(path + '\\'+ store_path, 'wb')
        f.write(picture.content)
        print('正在保存图片:' + picture_url)
        print('文件:' + name)


if __name__ == "__main__":
    content = '迪丽热巴'
    huaban = Huaban()
    huaban.get_picture_url(content)

下面打印的结果可以看出一共有7265张图片


爬取结果

小结:
1、对于刚开始用selenium的同学可以先选择chromedriver,虽然这个有界面浏览器可能爬起来比较慢,但是可以通过报错或者看下浏览器暂停的界面判断出是哪里的问题(比如时长暂停的时间太短了,没有加载出元素,又或者在加载中...)
2、其实这么简单的一个爬虫,里面的坑还不少的,
比如,本地的思路是每次获取记载的url,再遍历下载url列表里的图片,但是如果你是直接获取图片url所在的元素并存到列表里,后面再取出相应的url下载图片,虽然看起来回避之前的过程要简单一点,但是再运行到一半(大概几百张后,这个具体看运气咯)就会报错:

元素报错

selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
大概意思是说:意思就是Element已经过时,没有和当前页面进行绑定,主要是页面刷新或者跳转引起的,需要重新获取一次元素。
修改的方法:
获取元素之后,使用元素之前要重新花去一次元素
所以这里选择了获取元素后直接取url存到列表就比较稳定了;
3、这里还有一个调试比较麻烦的就是,每次下拉滑动的距离以及每次停留的时间大小,太大或大小都有可能导致提前结束爬虫;
4、这里其实还有一个思路就是:最开始的分析可以看出,每次加载出一页(20张)图片,就会有一个对应的url,我们可以通过构造这个每页的url获取所有的图片,这里只是提供一个思路,有兴趣的同学可以简单尝试一下是否可行;
5、最开始爬的时候可以先选择一些图片总数比较少的搜索词,这样可以比较快的看到效果,尽快调通,然后再试一些比较多的图片;
6、这里爬数量比较多的图片,可能速度稍微有点慢,用scrapy或者多线程的可能会比较快一点;

以上是小弟个人见解,如有错误请麻烦指出,多谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,837评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 那口无名无姓的井,埋不了三爷爷的魂。 人死以后,土藏身,井埋魂,这是妻子老家的规矩。一星期前我们在浙江接到三爷爷病...
    文案摇滚帮阅读 511评论 0 2
  • 近期参加了一档关于思维的收费课程,系统探讨模型化思维。所有的内容是基于下面这句话的,思维方向决定了做事方式,做事方...
    知行菜根阅读 450评论 0 1
  • “你在外面是不是有人?”丈夫叶风问到。黄萍刚到家,鞋子还没脱。家里像往常一样飘散着酒精的味道。 “你说什么?今晚煲...
    凉风有刃阅读 537评论 0 0