python爬取百度图片(动态页面)

前言

现在百度图片加载并不是一页一页地加载出来的,直接请求得到的 HTML 代码里面,并没有我们需要的数据,因为这些信息是通过Ajax加载的,并且通过js渲染生成的。在爬取动态页面时,我们就需要分析这个网页的请求了。

大家可以先跳到代码部分先执行,观看效果

分析Ajax请求

打开百度图片搜索页面:地址
我们可以看到这个网页并没有翻页按钮,而当我们一直往下拉请求,网页会自动的给我们加载出更多内容,显然我们只能获得到第一页的html内容。

在这里插入图片描述 那我们要怎么获得所有页的数据呢?
我们在Chrome中打开开发者工具(F12)。我们点击Network,点击XHR标签。
然后我们刷新网页,将图片继续下拉。这个时候我们就可以看到XHR标签,在网页每一次加载的时候就会跳出一个请求(acjson…),点击它再点Preview,我们看到这是一条json数据,点开data,我们看到这里面有30条数据,每一条都对应着一张图片。

在这里插入图片描述返回上图所示页面,我们点击第一个请求,点击Headers,往下拉看到Query String Parameters,可以看到他的参数如下:

tn:resultjson_com
ipn:rj
ct:201326592
is:
fp:result
queryWord:spyder
cl:2
lm:-1
ie:utf-8
oe:utf-8
adpicid:
st:-1
z:
ic:0
hd:
latest:
copyright:
word:spyder
s:
se:
tab:
width:
height:
face:0
istype:2
qc:
nc:1
fr:
expermode:
force:
pn:30
rn:30
gsm:1e

一个地址就是由一个基础网址加上如上图的参数组成,如下图所示
https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=spyder&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word=spyder&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn=30&rn=30&gsm=1e
queryWord和word就是我们搜索的值,pn的值即是刷新出来的图片数量,我们会发现每一个请求的pn参数都会加30。

当搜索关键字是中文时,比如我搜索大学
在这里插入图片描述
可以看到,queryWord和word的 值都变成%E5%A4%A7%E5%AD%A6了,啥情况呢,我要的是大学,怎么变成这个东西了呢?
原来, 还需要一顿操作:

>>>import urllib
>>>keyword="大学"
>>>keyword=urllib.parse.quote(keyword)
>>>keyword
'%E5%A4%A7%E5%AD%A6'

这样我们就成功找到我们需要的信息位置了,我们可以在请求头中看到存放json数据的url地址,终于可以开始了

import urllib
def get_urlset(keyword,page):#获取存放json数据的url地址,keyword即是输入的值,page为获得的url地址的个数
	url_list=[]
    kw=urllib.parse.quote(keyword)
    for j in range(page):
        p=j*30        
        url_list.append("https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord="+kw+"&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word="+kw+"&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn="+str(p)+"&rn=30&gsm=b4")
    return url_list

获得网址内容

加headers是为了伪装成浏览器访问。
加proxies是为了加代理,免费的代理只能维持一会可能就没用了,自行更换。

import requests
def get_html(url):#解析网址
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
    proxies = {'http': '117.91.250.131:9999'}
    try:
        resp = requests.get(url, headers=headers)
    except:
        resp = requests.get(url, headers=headers, proxies=proxies)
    return resp
    

利用上述方法get_html(url).text获得文本内容,get_html(url).content获得二进制代码,我们到此为止还没有用到。

解析json

我们点击第一个请求,点击Preview,打开其中的一个data,我们前面说过每一条data都对应一张图片,打开data,果然在hiverURL我们看到了图片地址
在这里插入图片描述好了,知道图片具体在哪了,用如下代码获得图片地址

import json
def parse_json(text):#解析json获得图片地址
    img_url=[]
    try:	#多用用try,防止加载失败,程序退出
        result=json.loads(text)
        if result:
            for i in result.get("data"):
                img_url.append(i.get("hoverURL"))
        return img_url
    except:
        print("获取图片地址失败")

创建文件夹

大家爬出来的图片肯定不希望散乱着弄出来,想要要用一个子文件夹包起来。如图所示。
在这里插入图片描述这里的“E:/学习/爬虫/百度图片”,是根目录,在跑程序之前要提前创建好哟,路径大家自行修改。

如何创建子文件夹呢,如下:

def mkdir(path):
    # os.path.exists(name)判断是否存在路径
    # os.path.join(path, name)连接目录与文件名
    isExists = os.path.exists(os.path.join("E:/学习/爬虫/百度图片", path))
    if not isExists:
        print('makedir', path)
        os.makedirs(os.path.join("E:/学习/爬虫/百度图片", path))
        os.chdir(os.path.join("E:/学习/爬虫/百度图片", path))
        return True
    else:
        print(path, 'already exists')
        return False
   

保存图片

def open_img(img,Number):#打开并保存图片到文件中
    if img:
        
        filename=keyword+str(Number)+".jpg"
        with open (r"E:/学习/爬虫/百度图片/"+keyword+r'/'+filename,'wb') as f:
            try:
                f.write(get_html(img).content)
                print(filename+"下载成功")
            except:
                print("读取文件失败")

最后获得的文件及文件名如下图所示:

在这里插入图片描述

代码

在跑程序之前要把保存图片的文件夹创建好哟,我的路径是"E:/学习/爬虫/百度图片",大家自行修改。还有就是可能如下四个包某些包要自行导入,我用的Anaconda 的spyder已经都导入好了,可以直接使用。

import urllib
import json
import requests
import os
import time

def get_urlset(keyword,page):#获得网址链接集合
    url_list=[]
    kw=urllib.parse.quote(keyword)
    for j in range(page):
        p=j*30        
        url_list.append("https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord="+kw+"&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word="+kw+"&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn="+str(p)+"&rn=30&gsm=b4")
    print(page)
    return url_list

def get_html(url):#获得网址内容
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
    proxies = {'http': '117.91.250.131:9999'}
    try:
        resp = requests.get(url, headers=headers)
    except:
        resp = requests.get(url, headers=headers, proxies=proxies)
    return resp


#text=get_html(get_urlset("湖北中医药大学")[0].text)

def parse_json(text):#解析json获得图片地址
    img_url=[]
    try:
        result=json.loads(text)
        if result:
            for i in result.get("data"):
                img_url.append(i.get("hoverURL"))
        return img_url
    except:
        print("获取图片地址失败")
        
#print(parse_json(text) )    

def mkdir(path):
    # os.path.exists(name)判断是否存在路径
    # os.path.join(path, name)连接目录与文件名
    isExists = os.path.exists(os.path.join("E:/学习/爬虫/百度图片", path))
    if not isExists:
        print('makedir', path)
        os.makedirs(os.path.join("E:/学习/爬虫/百度图片", path))
        os.chdir(os.path.join("E:/学习/爬虫/百度图片", path))
        return True
    else:
        print(path, 'already exists')
        return False
    
def open_img(img,Number):#打开并保存图片到文件中
    if img:
        
        filename=keyword+str(Number)+".jpg"
        with open (r"E:/学习/爬虫/百度图片/"+keyword+r'/'+filename,'wb') as f:
            try:
                f.write(get_html(img).content)
                print(filename+"下载成功")
            except:
                print("读取文件失败")
                

    
def main(keyword,page):#主函数
    mkdir(keyword)
    urlset=get_urlset(keyword,page)
    Number=0#用来计数
    for url in urlset:
        Text=get_html(url).text
        img_url=parse_json(Text)
        if img_url:
            for img in img_url:
                open_img(img,Number)
                Number+=1
if __name__ == '__main__':
    # 计时
    t1 = time.time()
    keyword=input("请输入你要爬取的图片:")
    page=input("请输入你要爬取的页数:") 
    page=int(page)         
    main(keyword,page)
    print(time.time() - t1)


运行结果如下
在这里插入图片描述

在这里插入图片描述

  • 12
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值