前段时间学习爬虫的时候,看了b站一个视频,感觉受益良多,其中的百度图片爬虫让我觉得很nice,今天想做一个神经网络的性别分类,需要用到男人和女人的图片,我就又想起了它,顺手整理了一下,分享出来。话不多说,先上效果图。
这里是全部代码
import requests
import os
import json
from threading import Thread
import numpy as np
# import threading
class baidu_photo():#获取图片数据
urls = []#装载返回的图片数据,json数据
def getpages(self,kw,num):
'''
:param kw:搜索关键字
:param num: 爬取图片的数目,num*30
:return: 列表
'''
url='https://image.baidu.com/search/acjson'#百度图片搜索地址
#请求头,将爬虫伪装成谷歌浏览器,如果不想写,有个包可以自动产生请求头(忘了,,,)
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
}
params=[]
for i in num:#num为请求的数目,是一个列表,一次请求三十张图片
#下面的一堆参数,在网址里面,按F12,调出开发者选项,在network里面,选择XHR,百度的图片刷新是ajax,所以只需要看xhr即可,点击刷新,就可以找到
params.append({
'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': i,#更换此参数,将返回不同的页面
'rn': '30',
'gsm': '3c',
'1590113448337': '',
})
p_thread=[]
for i in params:#迭代上面获取的页面
# res=requests.get(url,i)
# res=json.loads(res.text,strict=False)
# urls.append(res['data'])
p=Thread(target=self.Thead,args=(url,i,headers))#使用线程,每三十张一个线程爬取
p.start()
p_thread.append(p)#将线程加入线程列表
[i.join() for i in p_thread]#所有线程列表加入完成后,开始阻塞运行线程,join为阻塞模式,如果不使用,则主程序结束线程结束,使用则可以让所以线程爬虫爬取完毕
#因为线程是依赖于主进程的,线程与进程一同运行,爬虫的速度肯定慢于主进程(不负责任的说,,,应该是这个样子)
print('获取图片地址成功')
return self.urls
def Thead(self,url,i,headers):#线程开始
res = requests.get(url, i,headers=headers)#线程发送get请求,获取返回值(json数据,如果是个html页面就说明上面那个params出错了)
res = json.loads(res.text, strict=False)#json解析返回值,变成字典类型{'key','value'}是字典"{'key','value'}"是json,通俗的说json是一个字典样式的字符串
self.urls.append(res['data'])#将json里面包含图片url的数据存入全局列表urls
# pass
def get_images(self,kw,img_urls,dir):#下载图片
'''
:param kw:请求关键字,同时作为图片存储的文件夹名称
:param img_urls:图片地址
:param dir:保存的目录
:return:none
'''
# print(img_urls)
x=0#图片的初始名字
dir=dir+'/'+kw#创建一个文件夹,名字为搜索的关键字
if not os.path.exists(dir):#判断该文件夹是否存在
print('创建目录!')
os.makedirs(dir)#不存在创建目录,值得一提的是,makedir只能创建当前路劲下一层文件夹,如果多一层就会报错,使用makedirs
for data in img_urls:#获取每一次请求的数据
for i in data:#获取一次请求里面所有的数据
if i.get('thumbURL')!=None:#判断键thumbURL是否为空/存在
res=requests.get(i.get('thumbURL'))#得到了图片的url,发起get请求
print(f'正在下载{i.get("thumbURL")}')
open(f'{dir}/{x}.jpg','ab').write(res.content)#以追加的方式发开一个图片文件,名字为x.jpg,保存的为二进制文件,使用ab,res.content为二进制数据
x+=1
def start(self,num):#开始爬取
keyWord = input('请输入下载内容:')#输入搜索关键字
# num = 1
p_list = self.getpages(keyWord, num=num)#调用函数
self.get_images(keyWord, p_list, './baidu_photo')
if __name__ == '__main__':
baidu=baidu_photo()
# num=5
num = int(input('请输入下载数目(30*):'))
number=np.random.randint(1,20,num)*30#因为是使用的百度搜图,为了防止每次搜出来的都一样,选择了随机数,randint,从1到20生成num个数,返回一个列表
print(number)
# num=3
baidu.start(num=number)#开始爬取
这个东西我还弄了一个qt页面,但是,,老是出问题,我嗯是裂开了,如果有兴趣的可以试试,我也一并放这里。
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'baidu.ui'
#
# Created by: PyQt5 UI code generator 5.14.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_baidu(object):
def setupUi(self, baidu):
baidu.setObjectName("baidu")
baidu.resize(520, 383)
baidu.setStyleSheet("background-color:rgb(146,178,173);")
self.centralwidget = QtWidgets.QWidget(baidu)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(90, 10, 251, 61))
self.label.setStyleSheet("font-size:40px;\n"
"color:white;")
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(160, 130, 181, 31))
self.lineEdit.setObjectName("lineEdit")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(80, 130, 71, 31))
self.label_2.setObjectName("label_2")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(260, 180, 81, 28))
self.pushButton.setStyleSheet("border:1px solid black;\n"
"border-radius:5px;\n"
"background-color:black;\n"
"color:white;\n"
"font-size:20px;")
self.pushButton.setObjectName("pushButton")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(380, 10, 121, 301))
self.textEdit.setObjectName("textEdit")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(400, 0, 72, 15))
self.label_3.setObjectName("label_3")
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setGeometry(QtCore.QRect(160, 180, 91, 31))
self.lineEdit_2.setObjectName("lineEdit_2")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(80, 180, 71, 31))
self.label_4.setObjectName("label_4")
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setGeometry(QtCore.QRect(0, 304, 61, 21))
self.label_5.setStyleSheet("border:1px solid blue;")
self.label_5.setObjectName("label_5")
baidu.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(baidu)
self.menubar.setGeometry(QtCore.QRect(0, 0, 520, 26))
self.menubar.setObjectName("menubar")
self.menu = QtWidgets.QMenu(self.menubar)
self.menu.setObjectName("menu")
baidu.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(baidu)
self.statusbar.setObjectName("statusbar")
baidu.setStatusBar(self.statusbar)
self.menubar.addAction(self.menu.menuAction())
self.retranslateUi(baidu)
self.pushButton.clicked.connect(self.baidu_spader)
QtCore.QMetaObject.connectSlotsByName(baidu)
def retranslateUi(self, baidu):
_translate = QtCore.QCoreApplication.translate
baidu.setWindowTitle(_translate("baidu", "MainWindow"))
self.label.setText(_translate("baidu", "批量图片下载"))
self.label_2.setText(_translate("baidu", "图片类型:"))
self.pushButton.setText(_translate("baidu", "下载"))
self.label_3.setText(_translate("baidu", "下载日志"))
self.lineEdit_2.setPlaceholderText(_translate("baidu", "输入数*30张"))
self.label_4.setText(_translate("baidu", "图片数量:"))
self.label_5.setText(_translate("baidu", "Spider"))
self.menu.setTitle(_translate("baidu", "百度图片"))
这是qt设计出来直接生成的,,额,我好像忘记拉槽函数了,,,卧槽,打着字打着我似乎突然想起了我原先为什么老是失败了,,,,醉了,
好吧,废话少说,作者本身只是一个初学者,再加上这个代码放了一段时间了,注释不一定全对,,(别喷我,,,),
这个是在b站的一个视频里面老师操作的,我个人觉得这个视频很棒,初学者入门是我见过最好的了,我把链接放这里,大家有兴趣可以去看看,https://www.bilibili.com/video/BV1RJ411z7tH,课程名字是,最新Python爬虫项目实战全程实录(完结) #学完这个课所有爬虫都能写
这个项目在这个课程的倒数第三个,百度图片爬取。大家懂不起可以去看视频,这里的博客,我只是作为一个笔记,(经常不小心删代码,,这种打了一堆注释的代码,,我还是有点心疼的,即使它并不是完美也不高级)
溜了,,,,