1.需求目的
在做本科毕业设计的时候,女朋友选的课题时对于不同国家硬币的识别,这无疑将会用到深度学习以及机器学习的理论和方法来进行识别。但是前提是必须先拿一些样本数据在神经网络中进行训练,而每个币种也都需要三四百左右有效图片(就是那种含有用用信息的图片),这可当时愁坏了女朋友,我不忍心看她发愁,于是就揽下了图片资料的搜集这一部分的任务。
2.爬取原理
由于此次我们的爬取对象为Google浏览器,所以我就默认大家已经可以成功翻墙。如果大家还是翻不了,可以私聊找我,免费分享资料。
接下来我来介绍一下Selenium,Selenium它是一个用于Web应用程序自动化测试工具。它可以直接运行在浏览器中,就像真正的用户在操作一样。可以在受程序控制的窗口,让程序来模拟人的点击、下拉、输入、选择等操作,从而得到我们想要的数据。
selenium支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。此次实验我使用的浏览器为Chrome浏览器。
Webdriver在我理解看来,它是一个可以产生一个受程序控制的浏览器模拟器,如果我们使用selenium+webdriver组合来爬取信息的话,那么我们所有的活动都是发生在这个模拟器之中的。
在此处我就先不展示微Webdriver的安装教程,如果后边有时间,我会尽力量将这个教程补全。
3.代码介绍
在程序中,我是定义了几个函数来分别实现获取图片的下载地址get_str()、重命名图片的名称rename()、以及图片的下载download()函数
# @Time : 2019/5/5 0:22
# @Author : kingback
# @File : pics_USA.py
# @Software: PyCharm
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import requests
import time
from time import sleep
import traceback
import os
import re
##################################################################
## 以下开始定义函数
## 首先一点需要明确,如果函数只是定义了,
## 而没有被调用,它是不会执行的
##################################################################
##该函数主要实现抓取网页内容的解析工作
##获取当前页面硬币图片的下载地址
def get_str(driver):
try:
try:
driver.find_element_by_id("irc-rac").click()
##模拟用户点击网页右边的下一个
except:
driver.find_element_by_xpath("//*[@id='irc-rac']/a").click()
except:
driver.find_element_by_class_name("Q8Bv4e").click()
driver.find_element_by_css_selector("div#irc-lac > a").click()
##上边的try except都是模拟点击下一个的,因为有时候单纯的使用id来寻找那个下一个控件的时候网页有时候会搜索不到
## 当id搜索不到的时候,就会采用xpath来定位这个空间
##如果还是不行,那就再通过class_name来定位,如果还是不行那就通过css选择器来定位
##一般来说通过id来定位就直接可以
# 使用xpath解析网页中硬币图片的下载地址,可以看出这只是摘取网页该路径下的内容,也就是网页下包含硬币图片的img字段
img = driver.find_element_by_xpath("//*[@id='irc_cc']/div[2]/div[1]/div[2]/div[1]/a/img")
# 因为字段中含有很多属性,经过chrome()的开发者模式发现该图片的下载地址存储在src属性里边
img_url = img.get_attribute("src")
##提取src属性数据
return img_url
##返回网页解析出来的图片下载地址
##该函数主要实现
##传入的两个参数一个为file,是当前爬取图片的种类,比如‘一欧元’
##img_url 为图片的下载地址
##返回初步处理的文件名 例如‘一欧元/0322.jpg.jpg’或‘一欧元/0566.jpg’或‘一欧元/58777.jpg.wddcvcrrcc.jpg’
##总之返回数据多样,我们将会在rename函数中规范处理文件名称
def get_fileneme(file,img_url):
lists = re.split(r'/', img_url)
#将img_url 字符串按照‘/’拆分为数组lists
## lists数组的倒数第一个(在数组中表现形式为-1)数据即为我们需要的文件名称,但是此处得到的图片命名格式不规范
filename=os.path.join(file,lists[-1])
#考虑到有些图片的网页下载地址最后几位不是‘.jpg’结尾,于是我们在其文件名称上都手动加上‘.jpg’
filename = filename + ".jpg"
## 返回初步处理得到的文件名称
return filename
##再次处理已经拆分出来的图片名字,将一些命名不规范的图片统一规范
def rename(filename):
## 由于我们通过函数get_filename()得到的文件名称不规范
lists = re.split(r'.jpg', filename)
##使用re库对传入的filename按照‘.jpg’拆分
##比如‘一欧元/0322.jpg.jpg’ 拆分完后lists[0]内就是我们需要的规范文件名,为‘一欧元/0322’
filename_reshape = lists[0] + ".jpg"
##再对已经处理好的文件名进行字符串拼接,此时的文件名为 ‘一欧元/0322.jpg’
return filename_reshape
##返回规范的图片保存名字
##创建文件夹操作,fileame为要创建的文件夹的名字
def mkdir(filename):
#判断该文件夹是否存在
if os.path.exists(filename) is False:
##如果不存在那就创建该文件夹
os.makedirs(filename)
##该函数主要实现图片地址的下载,需要传入两个参数
##url为要下载图片的网络连接地址,filename为图片要保存为的名字(规范版)
##该程序执行会返回两个结果,如果要下载的文件已经存在,那么直接返回‘file exites!’
##如果图片下载成功,直接返回图片的名字
def download(url, filename):
#首先要对需要下载的图片进行查询
#如果文件已经存在,直接返回result,不再继续往下执行
if os.path.exists(filename):
result="file exists!"
return result
##以下执行部分执行,则说明该文件不存在
#以下大可不必管,就是一个图片保存操作
try:
r = requests.get(url, stream=True, timeout=15)
r.raise_for_status()
with open(filename, 'wb') as f:
for chunk in r.iter_content(chunk_size=1024):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
f.flush()
return filename
except KeyboardInterrupt:
if os.path.exists(filename):
os.remove(filename)
raise KeyboardInterrupt
except Exception:
if os.path.exists(filename):
os.remove(filename)
以上的代码部分都是一些为实现整体的爬取过程而定义的几个小函数,接下来引出今天的大Boss,那就是我们的main函数:
##该函数为程序执行的主体部分,通过调用不同的函数来实现我们的数据爬取
def main():
#开始驱动浏览器打开页面
# 程序开始
#使用webdriver创建一个Chrome浏览器,受程序控制
driver = webdriver.Chrome()
driver.maximize_window()
##设置浏览器界面最大化
##定义要爬取的网页地址
start_urls=['https://www.google.com.hk/search?q=One+cent+picture&tbm=isch&source=hp&sa=X&ved=2ahUKEwiToZvMooLiAhXmslQKHUqjDJwQsAR6BAgJEAE&biw=1536&bih=498&dpr=1.25#imgrc=n64_jLKJUBJDuM:',
'https://www.google.com.hk/search?q=5+cent+picture&tbm=isch&source=univ&sa=X&ved=2ahUKEwiUqdP_sILiAhUVpJ4KHc4WBo0QsAR6BAgHEAE&biw=1536&bih=498#imgrc=4nPkDSV6jzmtPM:',
'https://www.google.com.hk/search?q=10+cent+picture&tbm=isch&source=univ&sa=X&ved=2ahUKEwid7MzHrYLiAhUPsZ4KHV_pB-wQsAR6BAgJEAE&biw=1536&bih=498#imgrc=tSuhZO5ob26USM:',
'https://www.google.com.hk/search?biw=1536&bih=498&tbm=isch&sa=1&ei=rcvNXLOiLJf7-gT325fADA&q=25+cent+picture&oq=25+cent+picture#imgrc=SPdU2SyxQ6tyNM:',
'https://www.google.com/search?biw=1536&bih=498&tbm=isch&sa=1&ei=27rPXISNAc-U-gSw8bKIBw&q=1+dollar+coin&oq=1+dollar+coin&gs_l=img.3..0j0i67j0l8.1880.3046..4526...0.0..0.1243.3240.2-1j2j7-2......0....1..gws-wiz-img.HZop3grZwiA#imgrc=sQ7fSoquvqlbQM:',
'https://www.google.com/search?q=1+pound+coin&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjopoOy3oXiAhUMup4KHd4zAoQQ_AUIDigB&biw=1366&bih=656#imgrc=Cmk0QjVR04jZ8M:',
'https://www.google.com/search?q=1+euro+coins+pictures&tbm=isch&tbs=rimg:CUjCBQXqwMc1IjjLWV147TNxfsot4jFYTW-D-ZdMNwIH9RAPN4NbTVGbT2WIEN4N0zHChVTYC_1PLBmu4i8IjJ-HTzyoSCctZXXjtM3F-EdESbyfDkBffKhIJyi3iMVhNb4MRsM09YsukhJUqEgn5l0w3Agf1EBFIOTsFSko0GioSCQ83g1tNUZtPEQTD6K2VqDMHKhIJZYgQ3g3TMcIRBMPorZWoMwcqEgmFVNgL88sGaxFFsZNELmkR8SoSCbiLwiMn4dPPEXrc3fEvwxkL&tbo=u&sa=X&ved=2ahUKEwisss7e4YXiAhVPvZ4KHcg0DRgQ9C96BAgBEBg&biw=1366&bih=656&dpr=1#imgrc=SMIFBerAxzVhMM:']
##每个地址所对应的硬币种类
files=['一美分','五美分','十美分','二十五美分','一美元','一英镑','一欧元']
#每个种类的硬币要爬取的数量
nums=[1000,1000,1000,1000,1000,1000,200]
#开始对这些网页一个一个的爬取,for循环次数为start_urls内网页的个数
for i in range(len(start_urls)):
driver.get(start_urls[i])
##模拟浏览器开始自动访问第一个网址
sleep(6)
##设置时间等待,以确保页面加载完毕
print("******************** 当前爬取:", files[i], " *******************************\n\n")
number=1
#定义一个number变量来计数已经成功爬取的图片个数
#在当前路径下创建文件夹,比如创建‘一美分’
mkdir(files[i])
#当已经爬取的图片个数大于要爬取的图片个数的时候,停止执行该步骤
while (number<nums[i]):
#调用get_str函数获取硬币图片的下载地址
img_url=get_str(driver)
print("img_url",img_url)
##如果没有得到地址,输出网络不好
if(img_url==None):
print("当前网络状况不好!!!")
continue
# 定义图片名称
filename=get_fileneme(files[i],img_url) #未规范版
filename = rename(filename) #规范版
# 保存图片
aaa=download(img_url, filename)
##定义一个变量aaa来接收download的返回结果,如果返回为file exits则说明文件已存在,此时number不加1
##如果返回结果为filename,则说明成功保存图片,此时number+1
if (aaa == "file exists!"):
print("file exists!")
continue
elif(aaa==filename):
print("图片存储路径: ", aaa)
# sleep(0.5)
number+=1
##以下都是一些输出格式
print("*********************** 爬取", files[i], "完毕!!! *****************************")
if(i<=len(nums)):
print("***** 下一步爬取:",files[i+1]," *****")
print("*********************** 当前爬取进度",'%d / %d' % (i+1, len(nums))," *****************************\n\n")
sleep(3)
print("\n\n********************** 全部数据爬取完毕!!! ****************************")
driver.quit() # 关闭浏览器
##############################################################
#### 自定义函数结束,以上函数如果不被调用
#### 其本身是不会执行的。
##############################################################
其实当我们执行完之后,发现程序并没有真正的开始,那是因为,我们虽然定义了一个名叫main的函数,但是计算机不知道这个函数就是整个程序的入口,所以我们要想激活这个main函数,还需对其进行声明一下;
##真正的开始执行
##在前边定义的函数中选择 def main()这个函数
##并且执行该函数内的操作
if __name__=='__main__':
main()
当这些我们都准备好了之后,我们就可以运行该程序了,运行之后,接下来就是静待图片慢慢爬取完毕了。
虽然到这里程序已经可以完整的跑起来了,但是有个地方我还是忍不住,想要说几句;
##每个地址所对应的硬币种类
files=['一美分','五美分','十美分','二十五美分','一美元','一英镑','一欧元']
#每个种类的硬币要爬取的数量
nums=[1000,1000,1000,1000,1000,1000,200]
#开始对这些网页一个一个的爬取,for循环次数为start_urls内网页的个数
那就是这里,可以看的出来我们这次需要爬取的硬币的种类,对于第二个数组nums,我是用来定义每种硬币所要爬取的图片个数,例如这里的一欧元图片我们就只需要200张,而其它的则需要1000张。
4.运行结果
其它国家硬币的截图我就不再一一展示,如果有需要的可以私聊我,我看到后定会回复。