python爬虫——批量爬取百度图片

最近做项目,需要一些数据集,图片一张一张从网上下载太慢了,于是学了爬虫。
参考了大佬的文章:https://blog.csdn.net/qq_40774175/article/details/81273198
首先打开命令行,安装requests库

pip install requests

百度图片搜索的链接如下:

url='http://image.baidu.com/search/index?tn=baiduimage&fm=result&ie=utf-8&word='#百度链接

不信你在=后面加上要搜索的关键字,放在浏览器里试试。

下面分析一波百度图片,随便搜点什么东西,在浏览器里按F12打开开发者模式:
python爬虫——批量爬取百度图片_第1张图片
点Network标签、XHR、选上面那个name,可以看到请求方式是GET(另一种方式是POST),还有Request Headers中相关参数,表示浏览器访问的数据头。

下面伪装一个headers用来假装是浏览器访问:

headers = {
     #文件头,必须有,否则会安全验证
        "Accept":"application/json, text/javascript, */*; q=0.01",
        'Accept-Encoding': 'gzip, deflate, br',
		'Accept-Language': 'zh-CN,zh;q=0.9',
		'Connection': 'keep-alive',
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
        'Host': 'image.baidu.com',
        'Referer': 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=&st=-1&fm=result&fr=&sf=1&fmq=1610952036123_R&pv=&ic=&nc=1&z=&hd=&latest=©right=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E6%98%9F%E9%99%85',
        'Sec-Fetch-Mode': 'cors',
		'Sec-Fetch-Site': 'same-origin',
		'X-Requested-With': 'XMLHttpRequest'
    }

从上图的分析中可以看到Request Headers中相关参数,照着格式往里面写就行了,每个人可能不一样。最好都写上,如果有错误或者遗漏,GET到的网页信息将会是百度安全验证,这是因为百度认为你是机器访问。(解决这个问题花了好久)

下面爬取网页数据并存在data.txt中进一步分析

strhtml=requests.get(url,headers=headers)#get方式获取数据
string=str(strhtml.text)
with open("data.txt","w",encoding='utf-8') as f:#这个编码是个问题
    f.write(string)  #这句话自带文件关闭功能,不需要再写f.close()
print("已爬取,数据存入data.txt")

注意这里的解码方式,如果utf-8是乱码,可以试试GBK或者ISO-8859-1。没有解码方式会报错。

在网页中按Ctrl+U查看源码
python爬虫——批量爬取百度图片_第2张图片
分析一波发现,带有thumbURL的后面含有我们要下载的图片链接。
用正则表达式在我们爬到的网页数据中找:

img_url_regex = '"thumbURL":"(.*?)",'#正则匹配式
pic_url = re.findall(img_url_regex, string)  # 先利用正则表达式找到图片url

注意用正则匹配式需要import re
查阅re手册可知,.是匹配任意字符,*是匹配前一个元字符0到多次,?是匹配前一个元字符0到1次
findall的第一个参数是正则匹配式,第二个是要源文本,返回一个list

找到图片链接后,再用一遍get就很容易获得图片了,用文件操作把信息保存成一个.jpg即可。

有一个问题,就是一次搜索只能搜集大概30张图片,百度图片一页只能显示这么多,正常浏览是靠滚轮向下拉获得更多图片,那么爬虫怎么办呢?

解决办法:在URL链接最后面(包括关键字)加上&pn=

事实证明,&pn=表示当前页,注意,如果&pn=0时显示1-30张图片,&pn=1时则显示2-31张图片,因此每一页下载完图片后,需要计算此页共计多少张图片(len(pic_url )就能完事),然后再加到&pn=后面。
下载完一页接着下一页,直到全部下载完。

完整代码如下:

import requests#爬虫库
import re#正则表达式库
import os#系统库
import time#时间库

headers = {
     #文件头,必须有,否则会安全验证
        "Accept":"application/json, text/javascript, */*; q=0.01",
        'Accept-Encoding': 'gzip, deflate, br',
		'Accept-Language': 'zh-CN,zh;q=0.9',
		'Connection': 'keep-alive',
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
        'Host': 'image.baidu.com',
        'Referer': 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=&st=-1&fm=result&fr=&sf=1&fmq=1610952036123_R&pv=&ic=&nc=1&z=&hd=&latest=©right=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E6%98%9F%E9%99%85',
        'Sec-Fetch-Mode': 'cors',
		'Sec-Fetch-Site': 'same-origin',
		'X-Requested-With': 'XMLHttpRequest'
    }

url='http://image.baidu.com/search/index?tn=baiduimage&fm=result&ie=utf-8&word='#百度链接
print("@非常道")
keyword=input("请输入图片关键词:")
# keyword='cyberpunk'
countmax=eval(input("请输入要爬取的图片数量:"))
url=url+keyword+"&pn="
time_start=time.time()#获取初始时间

strhtml=requests.get(url,headers=headers)#get方式获取数据
string=str(strhtml.text)
# with open("data.txt","w",encoding='utf-8') as f:#这个编码是个问题
#     f.write(string)  #这句话自带文件关闭功能,不需要再写f.close()
# print("已爬取,数据存入data.txt")

#正则表达式取得图片总数量
totalnum = re.findall('
(.*?)
'
, string) print("百度图片"+totalnum[0]) img_url_regex = '"thumbURL":"(.*?)",'#正则匹配式 count=0#总共下载的图片数 index=0#链接后面的序号 page=0#当前搜集的页 while(1): strhtml=requests.get(url+str(index),headers=headers)#get方式获取数据 string=str(strhtml.text) print("已爬取网页") pic_url = re.findall(img_url_regex, string) # 先利用正则表达式找到图片url print("第"+str(page+1)+"页共收集到"+str(len(pic_url))+"张图片") index+=len(pic_url)#网址索引向后,跳到下一页继续搜刮图片 try:#如果没有文件夹就创建 os.mkdir('.'+r'\\' + keyword) except: pass for each in pic_url: print('正在下载第' + str(count + 1) + '张图片,图片地址:' + str(each)) try: if each is not None: pic = requests.get(each, timeout=5) else: continue except BaseException: print('错误,当前图片无法下载') continue else: string = '.' + r'\\' + keyword + r'\\' + keyword + '_' + str(count+1) + '.jpg' fp = open(string, 'wb') fp.write(pic.content) fp.close() count += 1 if countmax==count: break if countmax==count: break time_end=time.time()#获取结束时间 print('处理完毕,共耗时:'+str(time_end-time_start)+"秒") input("@非常道 按任意键继续")

咱也不是学html的,也不是学计算机的,会用就行……

有问题评论,没问题点赞 ↓ ↓ ↓ \downarrow\downarrow\downarrow

你可能感兴趣的:(Python,python,数据挖掘)