Python爬虫实战之爬取网站全部图片(二)

通过python 来爬取网站内所有的图片到本地  

第三篇是动态获取参数构造图片地址实现下载图片  传送门:https://blog.csdn.net/qq_33958297/article/details/82316019

 

这篇文章的目的是因为上一个文章里的地址已经无法访问了

考虑到可能有的新手没有办法去实验,这里又出了一个新的。

但是和那个网站的实现方式略微不同。

前面大致是一样的只是后面整套图片获取的时候 需要一些步骤。

 

爬取网址: https://www.mzitu.com/xinggan/page/1/

 

一.获得图片地址 和 图片名称

 

1.进入网址之后 按F12  打开开发人员工具点击elemnts

https://img-blog.csdn.net/20180902122050752?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzOTU4Mjk3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

 

 2.点击下图的小箭头 选择主图中的任意一个图片   那我们这里点击第一个 图片

 

   3.显示控制台 为了验证xpath是否正确

https://img-blog.csdn.net/20180902122050642?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzOTU4Mjk3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

 

 

 

    4.通过xpath获得a的href  和 title.

 

(请放大看)我们看到 他提示的是有24个 我们回到网站中看一下  在主页上数一下 他有32个 为什么我们拿到的是24个呢

其实仔细看一下能看到里面有几个图片位是插入的广告 

广告没有href 和data-origianl这两个属性

也就是说 我们获得的href 和title是没有任何问题的 那么留着为我们后面使用.

 

    5.我们还需要访问这个链接的请求头的信息 以备后面操作的时候来使用

 

这里可以看到 没有什么特别的请求头

 

6.获得每套图里的 所有图片.这也是我们的目的所在 不然前面那么多工序不是浪费吗。

但是我们进来之后发现 他只有一张图,需要点击下一页来获取剩下的图片。

那么我们这里的思路很简单,首先获取图片的地址,同时获取最大的页码,这样我们通过循环就可以自己构造出来他的图片地址

但是构造图片的话 我们需要知道他的规律  这样才可以保证我自己构造的地址不会有问题

那么开始吧:

第一张图

第二张图

 最后一张图

 

我们这里可以发现 他的图片地址很简单就是数字一直向后加就可以了。

 

7.获取图片地址和页码

上面是页码  下面是图片地址 

 

8.获得相应的请求头  

 

可以发现 需要注意的只有一个字段Referer 这里的地址就是我们访问这个页面进来的时候的那个地址 只要把那个地址给上就行了

这里需要Referer的原因是 因为网站基本都有防盗链 而防盗链就是看这个值到底有没有 如果直接请求的话 会返回一些错误的东西 或者错误等问题

 

那么至此 我们所有的东西都获得完成了下面开始写代码了

这里的代码 和上一篇的代码大致是相同的

 

9.对于404的处理 如果出现了404那就只有重新请求了

 

 

二.编写python代码实现爬取.

    1.需要用到的库有: 

      Requests   lxml    如果没有安装的请自己安装一下

    2.IDE : vscode

    3.python 版本: 2.7.15

    4.代码实现的是多线程下载,多线程的好处 就不用我多说了。

# -*- coding: utf-8 -*-

import requests
import os
from lxml import etree
from threading import *
from time import sleep
 
nMaxThread = 3  #这里设置需要开启几条线程
ThreadLock = BoundedSemaphore(nMaxThread)
 
gHeads = {
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
}
 
class Meizitu(Thread):
    def __init__(self,url,title):
        Thread.__init__(self)
        self.url = url  #这里的url在后面的referer中需要使用
        self.title = title
 
    def run(self):
        try:
            PhotoUrl,Page = self.GetPhotoUrlAndPageNum()
            if PhotoUrl and Page > 0:
                self.SavePhoto(PhotoUrl,Page)
        finally:
            ThreadLock.release()
 
    def GetPhotoUrlAndPageNum(self):
        html = requests.get(self.url,headers=gHeads)
        if html.status_code == 200:
            xmlContent = etree.HTML(html.text)
            PhotoUrl = xmlContent.xpath("//div[@class='main-image']/p/a/img/@src")[0][:-6] #01.jpg  正好是-6
            PageNum = xmlContent.xpath("//div[@class='pagenavi']/a[5]/span/text()")[0]
            return PhotoUrl,int(PageNum)
        else:
            return None,None
 
    def SavePhoto(self,url,page):
        savePath = "./photo/%s" % self.title
        if not os.path.exists(savePath):
            os.makedirs(savePath)
        for i in range(page):
            heads = {
                "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
                "Referer": "%s/%d" %(self.url,i+1),
                "Accept": "image/webp,image/apng,image/*,*/*;q=0.8"
            }
            j = 0
            while j<5:
                print (u"Download : %s/%d.jpg" % (self.title, i + 1))
                html = requests.get("%s%02d.jpg"%(url,i+1),headers=heads)
                if html.status_code == 200:
                    with open(savePath + "/%d.jpg"%(i+1),"wb") as f:
                        f.write(html.content)
                    break
                elif html.status_code == 404:
                    j+=1
                    sleep(0.05)
                    continue
                else:
                    return None
 
 
def main():
    while True:
        try:
            nNum = int(raw_input(u"请输入要下载几页: "))
            if nNum>0:
                break
        except ValueError:
            print(u"请输入数字。")
            continue
    for i in range(nNum):
        url = "https://www.mzitu.com/xinggan/page/%d/"%(i+1)
        html = requests.get(url,headers=gHeads)
        if html.status_code == 200:
            xmlContent = etree.HTML(html.content)
            hrefList = xmlContent.xpath("//ul[@id='pins']/li/a/@href")
            titleList = xmlContent.xpath("//ul[@id='pins']/li/a/img/@alt")
            for i in range(len(hrefList)):
                ThreadLock.acquire()
                t = Meizitu(hrefList[i],titleList[i])
                t.start()
 
 
if __name__ == '__main__':
    main()

效果图:

python在win环境下运行最大的问题就是编码,所以很多到时候都会出现乱码  建议大家在linux下操作 就不会用编码问题,但是并不影响下载只是输入的时候 不是很友好。

发布了25 篇原创文章 · 获赞 130 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_33958297/article/details/89388556