(二)批量下载百度网站图片

时间:2024-03-05 16:19:08

批量下载百度网站图片


获取图片的url链接

首先,打开百度图片首页,注意url中的index,将index修改成flip即可把瀑布流页面切换成传统翻页版(flip),这样有利于观察不同页数的url的规律。

对比不同页数的url可发现:pn参数是请求到的数量。通过修改pn参数来改变页数。其中gsm参数是pn参数的16进制表达,去掉无妨。%E6%9F%B4%E7%8A%AC为搜索的关键词的转码。

(1)第一页:https://image.baidu.com/search/flip?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1581675184369_R&pv=&ic=&nc=1&z=&hd=&latest=&copyright=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=柴犬
(2)第二页:https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=柴犬&pn=20&gsm=3c&ct=&ic=0&lm=-1&width=0&height=0
(3)第三页:https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=柴犬&pn=40&gsm=50&ct=&ic=0&lm=-1&width=0&height=0

因此url的格式为:

https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=%s&pn=%d\' %(name,i*20)#%s=name %d=i*20

(1) %用法
i.整数输出
%o —— oct 八进制
%d —— dec 十进制
%x —— hex 十六进制

print(\'%o\' % 20)  # 24
print(\'%d\' % 20)  # 20
print(\'%x\' % 20)  # 14

ii.浮点数输出
%f ——保留小数点后面六位有效数字

%.3f,保留3位小数位

%e ——保留小数点后面六位有效数字,指数形式输出

%.3e,保留3位小数位,使用科学计数法

%g ——在保证六位有效数字的前提下,使用小数方式,否则使用科学计数法

%.3g,保留3位有效数字,使用小数或科学计数法

print(\'%f\' % 1.11)  # 默认保留6位小数 1.110000
print(\'%.1f\' % 1.11)  # 取1位小数 1.1
print(\'%e\' % 1.11)  # 默认6位小数,用科学计数法 1.110000e+00
print(\'%.3e\' % 1.11)  # 取3位小数,用科学计数法 1.110e+00
print(\'%g\' % 1111.1111)  # 默认6位有效数字 1111.11
print(\'%.7g\' % 1111.1111)  # 取7位有效数字 1111.111
print(\'%.2g\' % 1111.1111)  # 取2位有效数字,自动转换为科学计数法 1.1e+03

iii.字符串输出
%s
%10s——右对齐,占位符10位
%-10s——左对齐,占位符10位
%.2s——截取2位字符串
%10.2s——10位占位符,截取两位字符串

print(\'%s\' % \'hello world\')  # 字符串输出  hello world
print(\'%20s\' % \'hello world\')  # 右对齐,取20位,不够则补位           hello world
print(\'%-20s\' % \'hello world\')  # 左对齐,取20位,不够则补位 hello world         
print(\'%.2s\' % \'hello world\')  # 取2位 he
print(\'%10.2s\' % \'hello world\')  # 右对齐,取2位         he
print(\'%-10.2s\' % \'hello world\')  # 左对齐,取2位 he     

获取图片地址(objURL)

在网页源代码中使用搜索objURL观察代码再配合正则表达式可得:

results = re.findall(r\'\"objURL\":\"(.*?)\", html)

(1)hoverURL 是鼠标移动过后显示的版本
(2)humbURL,middleURL是图片缩小的版本
(3)objURL是原图

代码框架

获取图片url代码

def getperpage(pn,name,num):#pn指爬取页数,name指搜索关键词,num=爬取的数量
    for i in range(int(pn)):
        print(\'正在获取第{}页\'.format(i + 1))
        url= \'https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=%s&pn=%d\' %(name,i*20)#%s=name %d=i*20
        headers = {
            \'Connection\': \'keep-alive\',
            \'Cache-Control\': \'max-age=0\',
            \'Upgrade-Insecure-Requests\': \'1\',
            \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36\',
            \'Sec-Fetch-Dest\': \'document\',
            \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\',
            \'Sec-Fetch-Site\': \'same-origin\',
            \'Sec-Fetch-Mode\': \'navigate\',
            \'Sec-Fetch-User\': \'?1\',
            \'Referer\': \'http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=%E7%99%BE%E5%BA%A6\',
            \'Accept-Language\': \'zh-CN,zh;q=0.9\',
        }
        response=requests.get(url,headers=headers)
        html=response.content.decode()#区分与response.txt的差别
        results=re.findall(r\'\"objURL\":\"(.*?)\"\', html)#(.*?)中的括号不能丢失
        #正则表达式解析:"objURL":"http://img.jk51.com/img_jk51/384725631.jpeg" 建议使用网页源代码用CTRL+F查询来观察,用F12的难以观察objURL的格式
        save_to_txt(results,name,i,num)

response.text

- 类型:str
- 解码类型: 根据HTTP 头部对响应的编码作出有根据的推测,推测的文本编码
- 如何修改编码方式:response.encoding=”gbk”

response.content

- 类型:bytes
- 解码类型: 没有指定
- 如何修改编码方式:response.content.decode(“utf-8”)

获取网页源码的通用方式

- response.content.decode()
- response.content.decode(“GBK”)
#解码方式可以根据响应头中找到Content-Type:text/html;charset=utf-8或者网页源码中content="text/html;charset=utf-8’\'来决定.
- response.text

以上三种方法从前往后尝试,能够100%的解决所有网页解码的问题

所以:更推荐使用response.content.decode()的方式获取响应的html页面

保存图片到本地

def save_to_txt(results,name,i,num):
   count = 0
   j=1
   root=\'D:\data\study\python\exercise\picture//\'+name
   if not os.path.exists(root):#建立文件路径
       os.mkdir(root)
   for result in results:
       count += 1
       if count<=num:#设置控制数量程序
           print(\'正在保存第{}个\'.format(j))
           try:
               pic = requests.get(result, timeout=10)
               time.sleep(1)
           except:
               print(\'当前图片无法下载\')
               j += 1
               continue
           path = root + \'/\' + name + str(i + 1) + \'-\' + str(j) + \'.jpg\'  # 图片路径及文件命名
           if not os.path.exists(path):
               with open(path, \'wb\')as f:
                   f.write(pic.content)
                   print(\'文件保存成功\')
               j += 1
           else:
               print(\'文件已存在\')

open()


(1)打开文件
file=open("文件名",“读写模式”)
(2)操作文件
(3)关闭文件
file.close()

注意事项

使用open方法,文件操作完毕之后必须关闭,否则长期保持对文件的连接状态,造成内存溢出的现象发生。

with open()

1)打开文件
with open ("文件名",“读写模式”) as file: 
(2)操作文件
(3)关闭文件(自动关闭)

主函数代码

def main():
    name=input(\'请输入想要搜索的关键词:\')
    pn=eval(input(\'请输入爬取的页数:\'))
    num=eval(input(\'请输入每页爬取的图片数量(每页最多为60):\'))
    getperpage(pn,name,num)
main()

引入库

import requests
import re
import os
import time

完整源代码

import requests
import re
import os
import time
def getperpage(pn,name,num):#pn指爬取页数,name指搜索关键词,num=爬取的数量
    for i in range(int(pn)):
        print(\'正在获取第{}页\'.format(i + 1))
        url= \'https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=%s&pn=%d\' %(name,i*20)#%s=name %d=i*20
        headers = {
            \'Connection\': \'keep-alive\',
            \'Cache-Control\': \'max-age=0\',
            \'Upgrade-Insecure-Requests\': \'1\',
            \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36\',
            \'Sec-Fetch-Dest\': \'document\',
            \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\',
            \'Sec-Fetch-Site\': \'same-origin\',
            \'Sec-Fetch-Mode\': \'navigate\',
            \'Sec-Fetch-User\': \'?1\',
            \'Referer\': \'http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=%E7%99%BE%E5%BA%A6\',
            \'Accept-Language\': \'zh-CN,zh;q=0.9\',
        }
        response=requests.get(url,headers=headers)
        html=response.content.decode()#区分与response.txt的差别
        results=re.findall(r\'\"objURL\":\"(.*?)\"\', html)#(.*?)中的括号不能丢失
        #正则表达式解析:"objURL":"http://img.jk51.com/img_jk51/384725631.jpeg" 建议使用网页源代码用CTRL+F查询来观察,用F12的难以观察objURL的格式
        save_to_txt(results,name,i,num)

def save_to_txt(results,name,i,num):
    count = 0
    j=1
    root=\'D:\data\study\python\exercise\picture//\'+name
    if not os.path.exists(root):#建立文件路径
        os.mkdir(root)
    for result in results:
        count += 1
        if count<=num:#设置控制数量程序
            print(\'正在保存第{}个\'.format(j))
            try:
                pic = requests.get(result, timeout=10)
                time.sleep(1)
            except:
                print(\'当前图片无法下载\')
                j += 1
                continue
            path = root + \'/\' + name + str(i + 1) + \'-\' + str(j) + \'.jpg\'  # 图片路径及文件命名
            if not os.path.exists(path):
                with open(path, \'wb\')as f:
                    f.write(pic.content)
                    f.close()
                    print(\'文件保存成功\')
                j += 1
            else:
                print(\'文件已存在\')





def main():
    name=input(\'请输入想要搜索的关键词:\')
    pn=eval(input(\'请输入爬取的页数:\'))
    num=eval(input(\'请输入每页爬取的图片数量(每页最多为60):\'))
    getperpage(pn,name,num)
main()





实例效果展示


参考

[1] https://www.cnblogs.com/Qqun821460695/p/12067699.html
[2]《Python网络爬虫与信息提取》http://www.icourse163.org/course/BIT-1001870001
[3] 格式化输出(%用法和fomat用法) https://www.cnblogs.com/felixwang2/p/9583522.html
[4] open()和with open()的区别 https://www.cnblogs.com/yangzhe0617/p/11038723.html