详细过程参考下面的网址,真的很不错的文章:
https://blog.youkuaiyun.com/mingzhiqing/article/details/82778954
下面附上上面博客的代码的详细注释,我有每一步去详细注释,很容易理解:
#爬取图片就3步,1.获取图片的大图网页, 2.以二进制方式存储, 3.file.write(大图网页.content)
from urllib.parse import urlencode
import requests
import re
import os
save_dir='./baidutu/'
def get_page(offset):
#这下面headers中Query String Parameters中的键值对
params = {
'tn': 'resultjson_com',
'ipn': 'rj',
'ct':'201326592',
'is':'',
'fp': 'result',
'queryWord': '帅哥',
'cl': '2',
'lm': '-1',
'ie': 'utf-8',
'oe': 'utf-8',
'adpicid':'',
'st': '-1',
'z':'',
'ic': '0',
'word': '帅哥',
's':'',
'se':'',
'tab':'',
'width':'',
'height':'',
'face': '0',
'istype': '2',
'qc':'',
'nc': '1',
'fr':'',
'expermode':'',
'cg': 'girl',
'pn': offset*30, #pn的值是30的倍数
'rn': '30',
'gsm': '1e',
'1537355234668':'',
}
url = 'https://image.baidu.com/search/acjson?' + urlencode(params)
try:
response = requests.get(url)
if response.status_code == 200: #status_code是状态码,等于200就表明服务器已成功处理了请求
return response.json()
except requests.ConnectionError as e:
print('Error', e.args)
def baidtu_uncomplie(url):
res = ''
c = ['_z2C$q', '_z&e3B', 'AzdH3F'] #这几个字符串是objURL中的部分
d= {'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', '_z2C$q':':', '_z&e3B':'.', 'AzdH3F':'/'}
if(url==None or 'http' in url):
return url
else:
j= url
for m in c:
j=j.replace(m,d[m])
for char in j:
# re.match("itcast","itcast.cn”) # match 第一个参数是需要匹配的字符串,第二个是源字符串
#[]表示匹配[]中列举的字符,^是字符串开始位置,\d表示匹配数字即0-9,$是字符串结束位置,+匹配前一个字符出现1次或者无限次,即至少有1次
if re.match('^[a-w\d]+$',char): #匹配是否有对应的字符
char = d[char] #再去d中匹配对应的键值对的值
res= res+char #拼接起来
return res
def get_images(json):
#get是取字典中键值对的值,这个函数取的所有值都是preview中的键
if json.get('data'): #若data的值不为空
for item in json.get('data'): #json.get('data')得到data下面的0到30所对应的所有字典,item是0到30中的一个
if item.get('fromPageTitle'): #如果页面标题不为空,即你要找的关键词不为空
title = item.get('fromPageTitle') #获取页面标题的值
else:
title='noTitle'
image = baidtu_uncomplie(item.get('objURL')) #调用解码函数,将加密的大图网址传给解码函数,得到解码后的网址
if(image):
#使用一个yield的时候,对应的函数就是一个生成器了。生成器的功能就是在yield的区域进行迭代处理
#yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值
yield {
'image': image,
'title': title
}
def save_image(item,count):
try:
response = requests.get(item.get('image')) #item.get('image')得到图片的网址,requests.get是获取网页
if response.status_code == 200: ##status_code是状态码,等于200就表明服务器已成功处理了请求
#format是格式化函数,{0}代表format中的第一个参数,即str(count),{1}代表第二个参数,即jpg
file_path = save_dir+'{0}.{1}'.format(str(count), 'jpg')
if not os.path.exists(file_path): #os.path.exists()就是判断括号里的文件是否存在的意思,括号内的可以是文件路径
with open(file_path, 'wb') as f:
f.write(response.content)
else:
print('Already Downloaded', file_path)
except requests.ConnectionError:
print('Failed to Save Image')
def main(pageIndex,count):
json = get_page(pageIndex) #在这调用了get_page,获取json
for image in get_images(json): #在这调用了get_images,这里的image是{'image': image,'title': title}这种形式
save_image(image, count) #在这调用了save_image,count是数字,用来做图片名字的
count += 1
return count
if __name__=='__main__':
if not os.path.exists(save_dir):
os.mkdir(save_dir)
count=1
for i in range(1,20): #一次30张图,取20次,就取了600张
count=main(i,count)
print('total:',count)