今天使用python爬取了2页天堂图片网的图片并保存到事先准备好的文件夹。网址:https://www.ivsky.com/tupian
下面来讲述一下爬取流程:
①:首先,我们进入天堂图片网,查看每一页图片网址的相同与不同之处,以便我们爬取:
第一页网址如下:
第二页网址如下:
第三页网址如下:
好的,经过我们的细心发现,我们找到了猫腻,没错,除了第一页,每一页的网址都为https://www.ivsky.com/tupian/index_页码.html这种格式。
②:然后,我们又发现每一页中的封面图片之内还包含多张图片,我们右击图片进行检查:
链接①为多图片链接(进入可查看其它图片),链接②为封面图片的链接:
③:我们进入链接①并以同样的方式查看第一张图片的代码:
好的,至此我们知道,我们要爬取的图片的url就为上图所示的url,只要爬取到每个图片的url,那么我们就可以爬取每张图片存放到文件夹啦。
下面我们的思路就很清晰了:
①:爬取给定页码的代码中的封面图片url
②:根据封面图片url进入内部,并查找每张图片url
③:根据获取的所有图片url爬取图片存入准备好的文件夹
函数说明:
①:get_html(url):参数url为每页的url;
②:get_big_url(url):参数url为每一页的url,返回值为list列表,list列表存放该页所有大图片的url;
③:get_little_url(url):参数url为一个大图片的url,返回值为list列表,list列表存放该大图片内部所有小图片的url;
④:save(folder,little_url):参数folder为事先准备好的存放图片的文件夹,参数little_url为每页所有大图片包含的小图片的url,无返回值;
⑤:get_picture(url):参数url为每一页的url,该函数目的在于协调各个函数,体现了各个函数间的调用顺序;
⑤:if __name == '__main__':执行脚本
好的,接下来我们上代码:(下面的标注中的大图片url指代封面url,小图片url指代内部图片url)
get_html(url)函数,用来根据给定url爬取相应页面源码
get_big_url(url)函数:
def get_big_url(url):
#获取网页代码
html = get_html(url).decode('utf8')
#big_img_url存放大图片的网址
big_url = []
a = html.find("il_img") + 17
##查询不到时a=-1,但是因为a = find +17,所以查询不到时为16
while a != 16:
b = html.find('"', a)
if b != -1:
#new_url存放大图片的网址
new_url = "https://www.ivsky.com/" + html[a:b]
# 将大图片地址放入列表big_url
big_url.append(new_url)
else:
break
#寻找下一个
a = html.find("il_img",b) + 17
return big_url
解释:
①为:将根据该页url爬取的代码放入html;
②为:在代码中查找“il_img”所在位置,后移17位为大图片url起始位置:
a = html.find("il_img") 返回的是"i"在整个源码中的位置。
③为:在源码中若找不到字符串"il_img",则返回a的值应为-1,但是因为在第二步我们将a的值加了17,所以找不到的情况下为16(这是基于源码中第16位不是我们要找的字符串的情况下,才可以这么写)。所以这句话表示,当我们找得到“il_img”时,执行下面语句。
④为:寻找a所在位置后的字符串引号
⑤为:若找得到引号,则执行下面语句
⑥为:html[a:b]为取源码中的a至b部分的字符串,并加上前缀“https://www.ivsky.com/”为大图片url
⑦为:将大图片url存放进数组big_url中
⑧为:若找到a找不到b则退出循环
⑨为:当找完一个大图片url后,我们要寻找下一个,那么我们就要从b所在位置起重新寻找字符串"il_img"所在位置,加17原因见②
最终返回值为存放所有大图片url的list列表
get_little_url(url)函数:该函数与获取大图片url的函数get_big_url(url)极为相似,故在此不做多余解释。
#参数url为大图片的url
def get_little_url(url):
# 获取网页代码
html = get_html(url).decode('utf8')
# little_img_url存放小图片的网址
little_url = []
a = html.find('<img src="//') +10
while a != 9:
b = html.find('.jpg', a, a+100)
if b != -1:
#new_url存放小图片的网址
new_url = "http:" + html[a:b+4]
#将小图片地址放入数组little_url
little_url.append(new_url)
else:
break
a = html.find('<img src="//',b) + 10
return little_url
# 返回小图片网址列表
save(folder,little_url)函数:
#将所有图片爬取并存入事先准备好的文件夹
def save(folder,little_url):
for each_url in little_url:
#下载的图片名称:
filename = each_url.split("/")[-1]
# print(each_url)
path = folder + "\\" + filename
with open(path,"wb") as f:
#爬取图片
picture = get_html(each_url)
f.write(picture)
print("图片",filename,"爬取成功!")
get_picture(url)函数
#获取图片
def get_picture(url):
# 大图片的url list集合
big_url = get_big_url(url)
for one_url in big_url:
#每次返回一个小图片的url集合
little_url = get_little_url(one_url)
#将该页图片爬取出来并存入事先准备好的文件夹
save("D:\\picture",little_url)
执行脚本:
1 if __name__ == '__main__':
2 # 循环page次,每次查找一页的图片集合
3 for page in range(1,3):
4 if page == 1:
5 url = "https://www.ivsky.com/tupian/"
6 else:
7 url = "https://www.ivsky.com/tupian/index_"+str(page)+".html"
8 print("总网址:",url)
9 get_picture("https://www.ivsky.com/tupian/")
10 print("爬取完成")
解析:
完整代码:
1 import urllib.request
2 import urllib.parse
3 import random
4 def get_html(url):
5 req = urllib.request.Request(url)
6 req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36 QIHU 360SE')
7
8 # IPList = ["122.224.65.201:3128","27.154.34.146:31527"]
9 # proxy = random.choice(IPList)
10 # proxy_supprot = urllib.request.ProxyHandler({"https:":proxy})
11 # opener = urllib.request.build_opener(proxy_supprot)
12 # urllib.request.install_opener(opener)
13
14 response = urllib.request.urlopen(url)
15 html = response.read()
16 return html
17
18 #获取大图片的网址
19 def get_big_url(url):
20 #获取网页代码
21 html = get_html(url).decode('utf8')
22 #big_img_url存放大图片的网址
23 big_url = []
24 a = html.find("il_img") + 17
25 ##查询不到时a=-1,但是因为a = find +17,所以查询不到时为16
26 while a != 16:
27 b = html.find('"', a)
28 if b != -1:
29 #new_url存放大图片的网址
30 new_url = "https://www.ivsky.com/" + html[a:b]
31 # 将大图片地址放入数组big_url
32 big_url.append(new_url)
33 else:
34 break
35 #寻找下一个
36 a = html.find("il_img",b) + 17
37 return big_url
38
39 #参数url为大图片的url
40 def get_little_url(url):
41 # 获取网页代码
42 html = get_html(url).decode('utf8')
43 # little_img_url存放小图片的网址
44 little_url = []
45 a = html.find('<img src="//') +10
46 while a != 9:
47 b = html.find('.jpg', a, a+100)
48 if b != -1:
49 #new_url存放小图片的网址
50 new_url = "http:" + html[a:b+4]
51 #将小图片地址放入数组little_url
52 little_url.append(new_url)
53 else:
54 break
55 a = html.find('<img src="//',b) + 10
56 return little_url
57 # 返回小图片网址列表
58
59 #将所有图片爬取并存入事先准备好的文件夹
60 def save(folder,little_url):
61 for each_url in little_url:
62 #下载的图片名称:
63 filename = each_url.split("/")[-1]
64 # print(each_url)
65 path = folder + "\\" + filename
66 with open(path,"wb") as f:
67 #爬取图片
68 picture = get_html(each_url)
69 f.write(picture)
70 print("图片",filename,"爬取成功!")
71 #获取图片
72 def get_picture(url):
73 # 大图片的url list集合
74 big_url = get_big_url(url)
75 for one_url in big_url:
76 #每次返回一个小图片的url集合
77 little_url = get_little_url(one_url)
78 #将该页图片爬取出来并存入事先准备好的文件夹
79 save("D:\\picture",little_url)
80
81
82
83
84
85 if __name__ == '__main__':
86 # 循环page次,每次查找一页的图片集合
87 for page in range(1,3):
88 if page == 1:
89 url = "https://www.ivsky.com/tupian/"
90 else:
91 url = "https://www.ivsky.com/tupian/index_"+str(page)+".html"
92 print("总网址:",url)
93 get_picture(url)
94 print("爬取完成")
完整代码
结果:
总结:
这次爬取天堂图片网用了半天时间,主要时间用于获取大图片小图片的url,在源码中查询字符串时,由于查询字符串之后对a与b进行了改变,所以跳出循环的条件不为a ==-1,而应是-1加上进行的偏移。