【爬虫 初出茅庐】 爬取并下载想要图片 源码 分析 + 分享

先上效果图。
如搜取并下载【鬼灭之刃】和【刀剑神域】相关图片
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

相关过程分析:

(PS:因为刚学爬虫没几天,若大佬发现有什么问题欢迎指正)

这里爬取的网站是免费提供图片的51贴图。若光爬取单一或者连续网页的图片是很简单的,但是如果要爬取用户输入的指定类型图片呢(如上述的【刀剑神域】),这就需要先找到用户输入串和对应url之间的联系。通过尝试发现,如找【天空之城】,改字符串直接包含在网页的url中:
在这里插入图片描述

那么,第一步:

我们可以将用户输入的串s填入
https://www.51tietu.net/pic/{}/.format(s)
那么就这个url就是我们第一步要爬的网站。不过,由于输入的串有可能是中文,直接丢进askurl函数可能会解码失败,所以要先对读入的串s进行下面操作

s = urllib.parse.quote(s)

这样就可以正常得到网页的html。

第二步:

观察网页的页数和url的关系,如到第二页
在这里插入图片描述发现后缀多了1,那么说明第一页就是/0,第二页/1 。 所以我们在爬取所有页数的时候,只需要控制循环添加url的后缀即可。即第一步部分如下图

 for idx in range(0,num//18 + 6): #num是用户需要的图片数,18是一页的数,后面加6保证能找得到那么多
        url_tmp = url1 + str(idx)
        html1 = askurl(url_tmp)
        soup1 = BeautifulSoup(html1, "html.parser")

第三步:

现在可以矛头指向图片本身了。先F12看封面图是否是我们要找的。在这里插入图片描述
但是发现封面图的链接打开并不是我们要找的原图,而点开封面得到的新网页才有我们的目标图片,但是这时候网页的url似乎又变得无序了起来。
在这里插入图片描述
我们现在离要找的图片的链接只差了一步。就是怎么得到上图的url呢?这时候我们回到前一步,找到前面入口处的对应超链接。(把鼠标移动到标题处即可显示),如图:
在这里插入图片描述
观察这里:href="/p/24998501.html"和前面那张图对比,发现就是后面那个链接https://www.51tietu.net/p/24998501.html的后缀,前面的https://www.51tietu.net/其实就是首页(原谅博主还没学HTML,术语上可能有问题)。那么自然想到,我们只需要爬取要找的图在此的超链接,然后相当于嵌套,变成爬取这个url的信息。那么要找的图的我们已经得到地址了。

最后一步:

最后一步就相当于最简单的爬虫了,爬取img标签下的图片链接即可。然后存入集合中(有可能爬到重复的)。最后,整理一遍思路:
1.先爬取包含s字符串(关键字)的网页
2.找到每个封面对于图片的超链接
3.再对超链接(目标图片的url)进行爬取,找到特定img标签下的链接

那么代码化的话就是一个循环控制页数,把所有超链接存入列表,后面一个循环控制对列表内的每个url进行爬取,再嵌套一个循环找到链接。

扫描二维码关注公众号,回复: 11639370 查看本文章

(第一次做爬虫,代码可能比较不成熟,望大佬指正)

源代码:

#-*- coding = utf-8 -*-
from bs4 import BeautifulSoup
import re
import urllib.request, urllib.error
import xlwt
import sqlite3
import requests
import os


def main():
    datalist = getData()
    download(datalist)

findLink = re.compile(r'href="(.*?).html"')
findImg = re.compile(r'src="(.*?)"',re.S)
findTitle = re.compile(r'<h1>(.*?)</h1>')
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
findJudge = re.compile(r'<span>(\d*)人评价</span>')
findInq = re.compile(r'<span class="inq">(.*)</span>')


flag = True


def askurl(url):
    head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36"}
    request = urllib.request.Request(url,headers = head)
    html = ""
    try:
        response = urllib.request.urlopen(request)
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        if hasattr(e,"code"):
            print(e.code)
        if hasattr(e,"reason"):
            print(e.reason)
        flag = False
    return html

def getData():
    datalist = []
    html = ""
   # num = 10
    s1 = ""
    s2 = ""
    s3 = ""
    s1 = input("输入你想查找图片的人物、角色、番剧名称或者风景等(一个词~)\n")
    num = eval(input("输入你想下载的图片的数量(0->1k),建议百张以内:\n"))
    print("====林肯死大头!!====\n")
    word = s1
    word = urllib.parse.quote(word)
    data = []
    url1 = "https://www.51tietu.net/pic/{}/".format(word)
    cnt = 0
    for idx in range(0,num//18 + 6):
        url_tmp = url1 + str(idx)
        html1 = askurl(url_tmp)
        soup1 = BeautifulSoup(html1, "html.parser")
        temp = str(soup1)
        for item in soup1.find_all(target="_blank"):
            item = str(item)
            for j in re.findall(findLink, item):
               # j = str(j)
                data.append(j)
                cnt += 1
                print("===以查找到%d张===\n" %cnt)
                if cnt>=num*3:
                    break
            if cnt >= num*3 :
                break
        if cnt>=num*3:
            break
    cnt = 0
    datalist = set(datalist)
    print("~~~~~正在缓存图片下载地址,请等待~~~~")
    for item in data:
        item = str(item)
        url = "https://www.51tietu.net{}.html".format(item)
        html = askurl(url)
        soup = BeautifulSoup(html,"html.parser")
        for i in soup.find_all('p'):
            i = str(i)
            for j in re.findall(findImg,i):
                if '.jpg' in str(j) :
                   datalist.add(str(j))
                   cnt += 1
                if len(datalist)>=num:
                    break
            if len(datalist) >= num :
                break
        if len(datalist) >= num :
            break
    datalist = list(datalist)


    return datalist



def download(datalist):
    dir = os.getcwd();  # 当前工作目录。
    cnt = 1
    print("··········downloading!(请等待数分钟~) ``````````````")
    for item in datalist:
         url = str(item)
         url.replace('[','')
         url.replace(']','')
         url.replace('\\' ,'')
      #   print(url)
         urllib.request.urlretrieve(url, dir + '\\result{}.jpg'.format(cnt))  # 下载图片。
         print("===已下载{}张!可在根目录查看图片下载过程~===\n".format(cnt))
         cnt += 1
    print("下载完成,去根目录看看爬取的成果吧~")
    a = input("===按任意键退出====")

main()

猜你喜欢

转载自blog.csdn.net/qq_45492531/article/details/106386274