爬取百度图片
前言:今天我们要爬取的是百度图片,最终目的是下载用户输入的任何类型 图片
1. 分析网页,确定是动态还是静态网页
首先我们先打开百度图片,右键检查然后搜索二次元,对网页进行分析,发现是ajax动态加载的,因为在往下翻翻阅图片的时候整个网页没有重新加载,所有确定是动态加载的,确定是动态加载的后就打开Network里面的XHR,这里面都是异步加载的数据包,之前动态加载图片的数据包都在里面,如图所示
2. 分析ajax加载的数据包,并找到请求url的规律
分析数据包后会发现一次请求就会向服务器获取30张图片,而且返回的数据中有三个图片地址,到时候提取数据的时候任取一个就好
将返回数据中的图片地址打开后发现正是我们需要下载的图片
分析请求url的不同之处与特别之处,发现了编码后的二次元在queryWord和word中,整个url的不同之处就是后面一部分,大概猜想一下,pn肯定就是第多少页而且一直是30的倍数,rn为返回来的数据为多少个,之前分析了一次请求的后返回的数据就是30张图片
那么最后面的两个参数是什么呢?我们尝试将其去掉然后去访问看能否获取到正确的数据,尝试后仍能获取正确的数据,这时我们就只需要改变pn即可以获取不同的图片了
我们先尝试让pn=0然后去请求数据,观察pn的初始值是多少,发现当pn为0时返回的数据中第一张图片正是网页中的第一张图片,所以pn的初始值为0,且pn是以30的倍数进行增长,一次请求返回30张图片。
3. 写代码
分析完url的规律后我们就可以开始写代码了,先写好整体的思路,然后再慢慢再去细化过程,这里我来说一下反爬中的一种方法,更改user-agent,下面是我所知的三种随机选择用户代理的方法:
- 自己在程序中定义一个列表,然后再使用random.choice方法去随机选择你保存在列表中的请求头
- 另外创建一个py文件,里面也定义好列表用random模块从而随机获取用户代理,然后再从自己正在写的的程序中去进行导入
- 使用fake_useragent模块,里面是已经封装好了的,直接调用random就可以获取不同的请求头,使用方法为
from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent':ua.random} # 因为获取的只是值,所以需加上User-Agent
写好整体思路
import requests
from fake_useragent import UserAgent
class BaiduImageSpider(object):
def __init__(self):
self.url = 'https://image.baidu.com/search/acjson?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&hd=&latest=©right=&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn={}&rn=30&gsm=1e&1587812157942='
self.headers = {'User-Agent':ua.random}
# 发送请求获取json
def get_data(self):
print(self.headers)
# 获取图片的url
def get_imageurl(self):
pass
# 向图片地址发送请求并下载图片
def save_image(self):
pass
def main(self):
self.get_data()
if __name__ == '__main__':
ua = UserAgent()
spider = BaiduImageSpider()
spider.main()
具体代码如下:
import requests,json,os,re,time
from fake_useragent import UserAgent
class BaiduImageSpider(object):
def __init__(self):
self.url = 'https://image.baidu.com/search/acjson?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&hd=&latest=©right=&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn={}&rn=30'
self.headers = {'User-Agent': ua.random} # 获取随机的用户代理
# 发送请求获取json
def get_data(self):
key = input('名字:')
page = int(input('页数:'))
for i in range(0,page):
url = self.url.format(key,key,i*30)
json_data = requests.get(url,headers = self.headers).text
response = json.loads(json_data,strict=False) # 这里直接解析会出错,所以增加一个strict为False,不严格检查json数据
self.get_imageurl(response)
time.sleep(1) # 发送一次请求后睡眠1秒
# 获取图片的url
def get_imageurl(self,response):
datas = response['data']
for data in datas:
try: # 进行异常捕获
image_url = data['thumbURL']
name = data['fromPageTitleEnc']
self.save_image(image_url, name)
except Exception:
pass # 捕获到异常不做任何处理
# 向图片地址发送请求并下载图片
def save_image(self,image_url,name):
name = re.sub(r'[.。!!/? ?\,【】|*&……)(%#]','',name) # 将一些非法字符替换为空,防止保存文件时报错
image = requests.get(image_url,headers = self.headers).content
filename = 'F:/图片/' # 图片保存路径
if not os.path.exists(filename): # 判断filename是否存在,不存在则创建
os.makedirs(filename)
try: # 因为替换的name可能补全,所以这里需要加上异常捕获
with open(filename+'{}.jpg'.format(name),'wb')as f:
f.write(image)
print('已下载 {}'.format(name))
except Exception: # 捕获到异常不做任何处理
pass
def main(self):
self.get_data()
if __name__ == '__main__':
ua = UserAgent()
spider = BaiduImageSpider()
spider.main()
最终结果如下
在下载图片的过程当中可能会有的文件无效,可能是因为我是随机用户代理的原因,如果谁找到了解决的方法,可以在下方留言告诉我,本章的学习到此结束,谢谢大家进行学习,如果有人觉得小编写的还不错或者说觉得小编的代码哪里还可以改进的,可以在下方进行留言一起交流学习,一起进步