Python 3 多线程下载百度图片搜索结果

今天来搜一搜「他」:百度图片搜索结果
搜索结果

下载简单页面

查看网页源码,发现同一张图片有四种网址:

"thumbURL": "http://img1.imgtn.bdimg.com/it/u=757023778,2840825931&fm=21&gp=0.jpg",
"middleURL": "http://img1.imgtn.bdimg.com/it/u=757023778,2840825931&fm=21&gp=0.jpg",
"hoverURL": "http://img1.imgtn.bdimg.com/it/u=757023778,2840825931&fm=23&gp=0.jpg",
"objURL": "http://imgsrc.baidu.com/forum/w=580/sign=b3bcc2f88a5494ee87220f111df4e0e1/78fed309b3de9c82913abac86a81800a18d84344.jpg",

经测试,前三种都有反爬虫措施,用浏览器可以打开,但是刷新一次就403 Forbidden。用爬虫获取不到图片。

第四种objURL是指图片的源网址,获取该网址会出现三种情况:

  1. 正常。继续下载
  2. 403 Forbidden。用continue跳过。
  3. 出现异常。用try except处理。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import requests
import re
import os

url = r'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=detail&fr=&sf=1&fmq=1447473655189_R&pv=&ic=0&nc=1&z=&se=&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E9%95%BF%E8%80%85%E8%9B%A4'
dirpath = r'F:\img'

html = requests.get(url).text
urls = re.findall(r'"objURL":"(.*?)"', html)

if not os.path.isdir(dirpath):
os.mkdir(dirpath)

index = 1
for url in urls:
print("Downloading:", url)
try:
res = requests.get(url)
if str(res.status_code)[0] == "4":
print("未下载成功:", url)
continue
except Exception as e:
print("未下载成功:", url)
filename = os.path.join(dirpath, str(index) + ".jpg")
with open(filename, 'wb') as f:
f.write(res.content)
index += 1

print("下载结束,一共 %s 张图片" % index)

下载结果

Exciting!

加载更多图片

但是上面的代码还有不足,当我们在网页中下拉时,百度会继续加载更多图片。需要再完善一下代码。

打开Chrome,按F12,切换到Network标签,然后将网页向下拉。这时浏览器地址栏的网址并没有改变,而网页中的图片却一张张增加,说明网页在后台与服务器交互数据。警察蜀黍,就是这家伙:
Chrome 抓包

xhr全称XMLHttpRequest,详细介绍见百度:XMLHTTPRequest_百度百科

点开看看:
Request URL

这么长一串网址,没有头绪。下拉网页,再抓一个xhr,对比一下它们的Request URL,使用在线文字对比工具:文本比较
文本对比结果

URL末尾有三处变化,最后一项看上去是时间戳,经过测试,直接把它删了也没事。

那么只需要研究pngsm值。继续下拉,到底的时候点加载更多图片,多抓几个对比一下URL的末尾部分:

pn=120&rn=60&gsm=78
pn=180&rn=60&gsm=b4
pn=240&rn=60&gsm=f0
pn=300&rn=60&gsm=12c
pn=360&rn=60&gsm=168

pn是一个60为步长的等差数列。gsm看上去是16进制,转换成十进制,发现它就是pn值,试了也可以删掉。

经测试,rn是步长值,最大只能取60,填入大于60的数,仍然以60为步长。如果删了rn,则步长值变为30。pn是图片编号,从0开始。

现在已经删了时间戳和gsm两项了,能不能让网址再短一点?继续观察,注意到:

&se=&tab=&width=&height=

这几项没指定值,肯定没用,把没值的都删了。

再看看这两项:

queryWord=%E9%95%BF%E8%80%85%E8%9B%A4
word=%E9%95%BF%E8%80%85%E8%9B%A4

这就是我们本次搜索的关键词。网址中的中文会被编码成UTF-8,每个中文3个字节,每个字节前加上%号。编码和解码方法如下:
中文编码解码

那么,我们可以写出指定关键词需要请求的所有网址:

1
2
3
4
5
6
7
8
import itertools
import urllib

def buildUrls(word):
word = urllib.parse.quote(word)
url = r"http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord={word}&cl=2&lm=-1&ie=utf-8&oe=utf-8&st=-1&ic=0&word={word}&face=0&istype=2nc=1&pn={pn}&rn=60"
urls = (url.format(word=word, pn=x) for x in itertools.count(start=0, step=60))
return urls

上面的代码中,itertools.count(start=0, step=60)表示一个从0开始,60为步长值的无限等差数列。
把这个数列的数字分别填入url作为pn值,就得到一个无限容量的url生成器,注意生成器必须用圆括号,如果写成中括号就成了列表,程序会在这一步无限执行下去。

下面开始解析每次获取的数据。我们点开看看,返回的是一串json数据。
接口返回数据

纳尼,这个objURL怎么不是HTTP开头的。试了几种方法都没成功,Google一下,找到这个:百度图片url解码

OK,既然明白了原理,我们写一个Python版的解密实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: loveNight
# @Date: 2015-11-14 21:11:11


"""解码百度图片搜索json中传递的url
抓包可以获取加载更多图片时,服务器向网址传输的json。
其中originURL是特殊的字符串
解码前:
ippr_z2C$qAzdH3FAzdH3Ffl_z&e3Bftgwt42_z&e3BvgAzdH3F4omlaAzdH3Faa8W3ZyEpymRmx3Y1p7bb&mla
解码后:
http://s9.sinaimg.cn/mw690/001WjZyEty6R6xjYdtu88&690
使用下面两张映射表进行解码。
"""


str_table = {
'_z2C$q': ':',
'_z&e3B': '.',
'AzdH3F': '/'
}

char_table = {
'w': 'a',
'k': 'b',
'v': 'c',
'1': 'd',
'j': 'e',
'u': 'f',
'2': 'g',
'i': 'h',
't': 'i',
'3': 'j',
'h': 'k',
's': 'l',
'4': 'm',
'g': 'n',
'5': 'o',
'r': 'p',
'q': 'q',
'6': 'r',
'f': 's',
'p': 't',
'7': 'u',
'e': 'v',
'o': 'w',
'8': '1',
'd': '2',
'n': '3',
'9': '4',
'c': '5',
'm': '6',
'0': '7',
'b': '8',
'l': '9',
'a': '0'
}

# str 的translate方法需要用单个字符的十进制unicode编码作为key
# value 中的数字会被当成十进制unicode编码转换成字符
# 也可以直接用字符串作为value
char_table = {ord(key): ord(value) for key, value in char_table.items()}


def decode(url):
# 先替换字符串
for key, value in str_table.items():
url = url.replace(key, value)
# 再替换剩下的字符
return url.translate(char_table)


if __name__ == '__main__':
url = r"ippr_z2C$qAzdH3FAzdH3Ffl_z&e3Bftgwt42_z&e3BvgAzdH3F4omlaAzdH3Faa8W3ZyEpymRmx3Y1p7bb&mla"
print(decode(url))

测试成功!

再从JSON字符串中找出所有的originURL:

1
2
re_url = re.compile(r'"objURL":"(.*?)"')
imgs = re_url.findall(html)

格式化JSON推荐使用Chrome的JSON handle插件
JSON hanlde插件效果

单线程下载脚本

整理一下流程:

  1. 生成网址列表
  2. 发送HTTP请求获取json数据
  3. 解析数据得到网址
  4. 下载

整合一下上面的代码,可以写出单线程的下载脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: loveNight

import json
import itertools
import urllib
import requests
import os
import re
import sys


str_table = {
'_z2C$q': ':',
'_z&e3B': '.',
'AzdH3F': '/'
}

char_table = {
'w': 'a',
'k': 'b',
'v': 'c',
'1': 'd',
'j': 'e',
'u': 'f',
'2': 'g',
'i': 'h',
't': 'i',
'3': 'j',
'h': 'k',
's': 'l',
'4': 'm',
'g': 'n',
'5': 'o',
'r': 'p',
'q': 'q',
'6': 'r',
'f': 's',
'p': 't',
'7': 'u',
'e': 'v',
'o': 'w',
'8': '1',
'd': '2',
'n': '3',
'9': '4',
'c': '5',
'm': '6',
'0': '7',
'b': '8',
'l': '9',
'a': '0'
}

# str 的translate方法需要用单个字符的十进制unicode编码作为key
# value 中的数字会被当成十进制unicode编码转换成字符
# 也可以直接用字符串作为value
char_table = {ord(key): ord(value) for key, value in char_table.items()}

# 解码图片URL
def decode(url):
# 先替换字符串
for key, value in str_table.items():
url = url.replace(key, value)
# 再替换剩下的字符
return url.translate(char_table)

# 生成网址列表
def buildUrls(word):
word = urllib.parse.quote(word)
url = r"http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord={word}&cl=2&lm=-1&ie=utf-8&oe=utf-8&st=-1&ic=0&word={word}&face=0&istype=2nc=1&pn={pn}&rn=60"
urls = (url.format(word=word, pn=x) for x in itertools.count(start=0, step=60))
return urls

# 解析JSON获取图片URL
re_url = re.compile(r'"objURL":"(.*?)"')
def resolveImgUrl(html):
imgUrls = [decode(x) for x in re_url.findall(html)]
return imgUrls

def downImg(imgUrl, dirpath, imgName):
filename = os.path.join(dirpath, imgName)
try:
res = requests.get(imgUrl, timeout=15)
if str(res.status_code)[0] == "4":
print(str(res.status_code), ":" , imgUrl)
return False
except Exception as e:
print("抛出异常:", imgUrl)
print(e)
return False
with open(filename, "wb") as f:
f.write(res.content)
return True


def mkDir(dirName):
dirpath = os.path.join(sys.path[0], dirName)
if not os.path.exists(dirpath):
os.mkdir(dirpath)
return dirpath

if __name__ == '__main__':
print("欢迎使用百度图片下载脚本!\n目前仅支持单个关键词。")
print("下载结果保存在脚本目录下的results文件夹中。")
print("=" * 50)
word = input("请输入你要下载的图片关键词:\n")

dirpath = mkDir("results")

urls = buildUrls(word)
index = 0
for url in urls:
print("正在请求:", url)
html = requests.get(url, timeout=10).content.decode('utf-8')
imgUrls = resolveImgUrl(html)
if len(imgUrls) == 0: # 没有图片则结束
break
for url in imgUrls:
if downImg(url, dirpath, str(index) + ".jpg"):
index += 1
print("已下载 %s 张" % index)

执行脚本:
单线程下载结果

查看同目录下的results文件夹,又看到了亲切的「他」。

多线程下载脚本

上面的代码仍然有改进空间:

  1. 从JSON数据看,该关键词相关的图片有一千多张,单线程下载太慢了,时间都花在网络和硬盘IO上。加上多线程可以大大提升效率。
  2. 既然1中已经获取到图片总数,那么网址的无限容量生成器可以改成list,方便添加多线程。

多线程一直没学好,想不到更优雅的写法,大家将就看一下吧,欢迎提出改进建议。

百度图片下载脚本之多线程版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: loveNight
# @Date: 2015-10-28 19:59:24
# @Last Modified by: loveNight
# @Last Modified time: 2015-11-15 19:24:57


import urllib
import requests
import os
import re
import sys
import time
import threading
from datetime import datetime as dt
from multiprocessing.dummy import Pool
from multiprocessing import Queue


class BaiduImgDownloader(object):

"""百度图片下载工具,目前只支持单个关键词"""

# 解码网址用的映射表
str_table = {
'_z2C$q': ':',
'_z&e3B': '.',
'AzdH3F': '/'
}

char_table = {
'w': 'a',
'k': 'b',
'v': 'c',
'1': 'd',
'j': 'e',
'u': 'f',
'2': 'g',
'i': 'h',
't': 'i',
'3': 'j',
'h': 'k',
's': 'l',
'4': 'm',
'g': 'n',
'5': 'o',
'r': 'p',
'q': 'q',
'6': 'r',
'f': 's',
'p': 't',
'7': 'u',
'e': 'v',
'o': 'w',
'8': '1',
'd': '2',
'n': '3',
'9': '4',
'c': '5',
'm': '6',
'0': '7',
'b': '8',
'l': '9',
'a': '0'
}

re_objURL = re.compile(r'"objURL":"(.*?)".*?"type":"(.*?)"')
re_downNum = re.compile(r"已下载\s(\d+)\s张图片")
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36",
"Accept-Encoding": "gzip, deflate, sdch",
}

def __init__(self, word, dirpath=None, processNum=30):
if " " in word:
raise AttributeError("本脚本仅支持单个关键字")
self.word = word
self.char_table = {ord(key): ord(value)
for key, value in BaiduImgDownloader.char_table.items()}
if not dirpath:
dirpath = os.path.join(sys.path[0], 'results')
self.dirpath = dirpath
self.jsonUrlFile = os.path.join(sys.path[0], 'jsonUrl.txt')
self.logFile = os.path.join(sys.path[0], 'logInfo.txt')
self.errorFile = os.path.join(sys.path[0], 'errorUrl.txt')
if os.path.exists(self.errorFile):
os.remove(self.errorFile)
if not os.path.exists(self.dirpath):
os.mkdir(self.dirpath)
self.pool = Pool(30)
self.session = requests.Session()
self.session.headers = BaiduImgDownloader.headers
self.queue = Queue()
self.messageQueue = Queue()
self.index = 0 # 图片起始编号,牵涉到计数,不要更改
self.promptNum = 10 # 下载几张图片提示一次
self.lock = threading.Lock()
self.delay = 1.5 # 网络请求太频繁会被封
self.QUIT = "QUIT" # Queue中表示任务结束
self.printPrefix = "**" # 用于指定在控制台输出

def start(self):
# 控制台输出线程
t = threading.Thread(target=self.__log)
t.setDaemon(True)
t.start()
self.messageQueue.put(self.printPrefix + "脚本开始执行")
start_time = dt.now()
urls = self.__buildUrls()
self.messageQueue.put(self.printPrefix + "已获取 %s 个Json请求网址" % len(urls))
# 解析出所有图片网址,该方法会阻塞直到任务完成
self.pool.map(self.__resolveImgUrl, urls)
while self.queue.qsize():
imgs = self.queue.get()
self.pool.map_async(self.__downImg, imgs)
self.pool.close()
self.pool.join()
self.messageQueue.put(self.printPrefix + "下载完成!已下载 %s 张图片,总用时 %s" %
(self.index, dt.now() - start_time))
self.messageQueue.put(self.printPrefix + "请到 %s 查看结果!" % self.dirpath)
self.messageQueue.put(self.printPrefix + "错误信息保存在 %s" % self.errorFile)
self.messageQueue.put(self.QUIT)


def __log(self):
"""控制台输出,加锁以免被多线程打乱"""
with open(self.logFile, "w", encoding = "utf-8") as f:
while True:
message = self.messageQueue.get()
if message == self.QUIT:
break
message = str(dt.now()) + " " + message
if self.printPrefix in message:
print(message)
elif "已下载" in message:
# 下载N张图片提示一次
downNum = self.re_downNum.findall(message)
if downNum and int(downNum[0]) % self.promptNum == 0:
print(message)
f.write(message + '\n')
f.flush()

def __getIndex(self):
"""获取文件编号"""
self.lock.acquire()
try:
return self.index
finally:
self.index += 1
self.lock.release()

def decode(self, url):
"""解码图片URL
解码前:
ippr_z2C$qAzdH3FAzdH3Ffl_z&e3Bftgwt42_z&e3BvgAzdH3F4omlaAzdH3Faa8W3ZyEpymRmx3Y1p7bb&mla
解码后:
http://s9.sinaimg.cn/mw690/001WjZyEty6R6xjYdtu88&690
"""

# 先替换字符串
for key, value in self.str_table.items():
url = url.replace(key, value)
# 再替换剩下的字符
return url.translate(self.char_table)

def __buildUrls(self):
"""json请求网址生成器"""
word = urllib.parse.quote(self.word)
url = r"http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&fp=result&queryWord={word}&cl=2&lm=-1&ie=utf-8&oe=utf-8&st=-1&ic=0&word={word}&face=0&istype=2nc=1&pn={pn}&rn=60"
time.sleep(self.delay)
html = self.session.get(url.format(word=word, pn=0), timeout = 15).content.decode('utf-8')
results = re.findall(r'"displayNum":(\d+),', html)
maxNum = int(results[0]) if results else 0
urls = [url.format(word=word, pn=x)
for x in range(0, maxNum + 1, 60)]
with open(self.jsonUrlFile, "w", encoding="utf-8") as f:
for url in urls:
f.write(url + "\n")
return urls

def __resolveImgUrl(self, url):
"""从指定网页中解析出图片URL"""
time.sleep(self.delay)
html = self.session.get(url, timeout = 15).content.decode('utf-8')
datas = self.re_objURL.findall(html)
imgs = [Image(self.decode(x[0]), x[1]) for x in datas]
self.messageQueue.put(self.printPrefix + "已解析出 %s 个图片网址" % len(imgs))
self.queue.put(imgs)

def __downImg(self, img):
"""下载单张图片,传入的是Image对象"""
imgUrl = img.url
# self.messageQueue.put("线程 %s 正在下载 %s " %
# (threading.current_thread().name, imgUrl))
try:
time.sleep(self.delay)
res = self.session.get(imgUrl, timeout = 15)
message = None
if str(res.status_code)[0] == "4":
message = "\n%s: %s" % (res.status_code, imgUrl)
elif "text/html" in res.headers["Content-Type"]:
message = "\n无法打开图片: %s" % imgUrl
except Exception as e:
message = "\n抛出异常: %s\n%s" % (imgUrl, str(e))
finally:
if message:
self.messageQueue.put(message)
self.__saveError(message)
return
index = self.__getIndex()
# index从0开始
self.messageQueue.put("已下载 %s 张图片:%s" % (index + 1, imgUrl))
filename = os.path.join(self.dirpath, str(index) + "." + img.type)
with open(filename, "wb") as f:
f.write(res.content)

def __saveError(self, message):
self.lock.acquire()
try:
with open(self.errorFile, "a", encoding="utf-8") as f:
f.write(message)
finally:
self.lock.release()


class Image(object):

"""图片类,保存图片信息"""

def __init__(self, url, type):
super(Image, self).__init__()
self.url = url
self.type = type


if __name__ == '__main__':
print("欢迎使用百度图片下载脚本!\n目前仅支持单个关键词。")
print("下载结果保存在脚本目录下的results文件夹中。")
print("=" * 50)
word = input("请输入你要下载的图片关键词:\n")
down = BaiduImgDownloader(word)
down.start()

执行脚本:

欢迎使用百度图片下载脚本!
目前仅支持单个关键词。
下载结果保存在脚本目录下的results文件夹中。
==================================================
请输入你要下载的图片关键词:
长者蛤
2015-11-15 19:25:11.726878 **脚本开始执行
2015-11-15 19:25:16.292022 **已获取 20 个Json请求网址
2015-11-15 19:25:17.885767 **已解析出 30 个图片网址
2015-11-15 19:25:17.917020 **已解析出 60 个图片网址
.....
.....中间省略
.....
2015-11-15 19:33:31.726739 已下载 980 张图片:http://bbs.nantaihu.com/bbs/UpImages2008/2010/8/3/U97946_201083171218512-2.jpg
2015-11-15 19:33:32.695518 已下载 990 张图片:http://pf.u.51img1.com/f9/7f/huangbaoling0_180.gif?v=20120224161006
2015-11-15 19:33:45.473957 已下载 1000 张图片:http://library.taiwanschoolnet.org/cyberfair2003/C0312970394/narrative.files/image018.jpg
2015-11-15 19:33:50.749544 **下载完成!已下载 1000 张图片,总用时 0:08:39.022666
2015-11-15 19:33:50.765169 **请到 F:\PythonWorkspace\Learn\results 查看结果!
2015-11-15 19:33:50.858880 **错误信息保存在 F:\PythonWorkspace\Learn\errorUrl.txt

合租室友太多,平时网速很慢,经常连百度都打不开,要刷新多次。下午测试的时候可以2分钟下完,现在居然要近9分钟。

errorUrl.txt的内容

无法打开图片: http://s3.t.itc.cn/mblog/pic/20136_20_14/f_b3a1be1796819229739.png
403: http://www.longhoo.net/gb/longhoo/culture/view/images/00024483.jpg
无法打开图片: http://bhyjk.cn/images/IMG44zj10.jpg
404: http://ebook.indaa.com.cn/upload/baike/images/2960001-2970000/2968900/adee30ddd41190838c10291d.jpg
抛出异常: http://www.jzxzj.com/images/xs.jpg
HTTPConnectionPool(host='www.jzxzj.com', port=80): Max retries exceeded with url: /images/xs.jpg (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x0851FBB0>: Failed to establish a new connection: [Errno 11002] getaddrinfo failed',))
抛出异常: http://static.acfun.mm111.net/h/image/20147/846b7553851b6edb2305c6b87f4aed71.jpg
HTTPConnectionPool(host='static.acfun.mm111.net', port=80): Max retries exceeded with url: /h/image/20147/846b7553851b6edb2305c6b87f4aed71.jpg (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x0888B710>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',))
抛出异常: http://static.acfun.mm111.net/h/image/2015-0-4/23ebeaf5-5130-4072-b90e-48ce4d122ac8.jpg
HTTPConnectionPool(host='static.acfun.mm111.net', port=80): Max retries exceeded with url: /h/image/2015-0-4/23ebeaf5-5130-4072-b90e-48ce4d122ac8.jpg (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x0888F1F0>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed',))
404: http://www.zipooo.com/tupian/1/%CE%EF%C1%F7%BF%EC%B5%DD.gif
无法打开图片: http://www.zhiyin.cn/hsbk/fakeimg/7939883.jpeg
无法打开图片: http://www.zhiyin.cn/hsbk/fakeimg/21753396.jpeg
.....

logInfo.txt内容:

2015-11-15 19:25:11.726878 **脚本开始执行
2015-11-15 19:25:16.292022 **已获取 20 个Json请求网址
2015-11-15 19:25:17.885767 **已解析出 30 个图片网址
2015-11-15 19:25:17.917020 **已解析出 60 个图片网址
2015-11-15 19:25:17.948262 **已解析出 60 个图片网址
2015-11-15 19:25:17.963895 **已解析出 60 个图片网址
2015-11-15 19:25:17.995146 **已解析出 60 个图片网址
2015-11-15 19:25:18.010769 **已解析出 60 个图片网址
2015-11-15 19:25:18.057638 **已解析出 60 个图片网址
2015-11-15 19:25:18.057638 **已解析出 60 个图片网址
2015-11-15 19:25:18.073264 **已解析出 60 个图片网址
2015-11-15 19:25:18.073264 **已解析出 60 个图片网址
2015-11-15 19:25:18.088890 **已解析出 60 个图片网址
2015-11-15 19:25:18.088890 **已解析出 60 个图片网址
2015-11-15 19:25:18.104516 **已解析出 60 个图片网址
2015-11-15 19:25:18.104516 **已解析出 60 个图片网址
2015-11-15 19:25:18.104516 **已解析出 60 个图片网址
2015-11-15 19:25:18.104516 **已解析出 60 个图片网址
2015-11-15 19:25:18.245137 **已解析出 60 个图片网址
2015-11-15 19:25:18.260764 **已解析出 60 个图片网址
2015-11-15 19:25:18.260764 **已解析出 60 个图片网址
2015-11-15 19:25:18.479555 **已解析出 60 个图片网址
2015-11-15 19:25:27.532965 已下载 1 张图片:http://imgsrc.baidu.com/baike/abpic/item/43e6c7335b379350ad4b5f92.jpg
2015-11-15 19:25:29.084964
无法打开图片: http://s3.t.itc.cn/mblog/pic/20136_20_14/f_b3a1be1796819229739.png
2015-11-15 19:25:29.522473 已下载 2 张图片:http://p4.qhimg.com/dr/200_200_/t0196ad8cefbc7a2c7c.jpg
2015-11-15 19:25:29.822650 已下载 3 张图片:http://library.taiwanschoolnet.org/cyberfair2003/C0312970394/narrative.files/image016.jpg
2015-11-15 19:25:29.938687 已下载 4 张图片:http://blog.ylib.com/public/Utilities/ImageReader.aspx?/0/6/06c67eaf-09db-40a8-a117-c577a6d05d08.jpg
....

仍然可以改进的地方:

  1. 如果要搜索多个关键词,buildUrls方法应该怎么改?
  2. 如果脚本中途意外结束(比如被熊孩子点了X),如何继续下载?
  3. 线程池中的线程数需要多次测试才能找到最优值。
loveNight wechat
我的微信公众号,放一些有趣的内容,不定期更新。