【爬虫】Selenium爬取动态网页的base64图片
- 文章简介
Selenium爬取动态网页的base64图片,并解决页面完整加载缓慢,base64字符串的获取和格式转码,一些页面不存在,部分照片无法加载等问题。后附源码。目录
- 1,需求
- 2,环境和使用的技术
- 3,难点
- 3.1,页面完整加载缓慢
- 3.2,base64字符串的获取和格式转码
- 3.3,一些页面不存在
- 3.4,部分照片无法加载
- 4,参考代码
1,需求
近日遇到需要爬取某网站的一些图片。图片所在页面为基础地址加上图片集的编号(类似:www.XXX.com/img/001
,其为restful风格的网址,后面的数字为图片集的编号)。进入页面后,由动态加载网页,其技术以我现在的水平还无从得知。图片以base64风格嵌在img标签中。我的目标就是要爬取所有图集中的图片,将其保存为png或jpg格式。
2,环境和使用的技术
使用的python版本是
Python 3.7.0
因为是动态加载的页面,在Chrome浏览器的network中抓包找不到相关加载base64的请求,目前我只知道可以使用
Selenium
获取加载完成后的网页源码后,使用
bs4(BeautifulSoup)
解析获取想要的base64字符串,当然也可以使用xpath等。
安装环境
如果未安装需要的库,可以直接进入CMD使用pip安装(PyCharm的话还要调整路径,VSCode可以直接安装,PyCharm可参考其他文章)
# 安装selenium
pip install selenium
# 安装bs4
pip install bs4# 如果下载慢可以用国内镜像,只需要在上述命令后添加: -i 国内python镜像地址
# 如:
# 安装selenium
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装bs4
pip install bs4 -i https://pypi.tuna.tsinghua.edu.cn/simple
3,难点
3.1,页面完整加载缓慢
问题
爬取的网站页面上个别部分加载比较慢,网页加载完成所需要的时间很长。页面加载过程线程阻塞,要页面停止加载才会执行后面的代码,每爬一个页面加载时间都很长,导致爬取速度很慢。
解决方案
虽然加载完成很慢,但是所需要的图片几秒钟就可以加载完成,所以我想着可不可以直接代码控制网页自动停止加载。
首先我想到的是直接调用js的停止执行命令,但是发现线程阻塞,不能够使用
'''这里只演示关键部分,表达思想,省略了一些代码和参数''' url = 'www.XXX.com/img/001' broswer = webdriver.Chrome() broswer.get(url) # 只有页面加载完成后,才能执行下面代码,也就是页面加载完成后,才能执行停止页面加载的代码... browser.execute_script('window.stop()')
一通操作后,我在网上找到了让get不阻塞线程的方法,使得自己能够控制加载时间:
from selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesLOAD_TIME = 3 path = "C:\...\chrome.exe" options = Options() ##### 设置get不阻塞线程 ##### desired_capabilities = DesiredCapabilities.CHROME desired_capabilities["pageLoadStrategy"] = "none" broswer = webdriver.Chrome(desired_capabilities=desired_capabilities) broswer.get(url) ##### 设置睡眠时间,LOAD_TIME秒后执行停止加载的js命令 ##### time.sleep(LOAD_TIME) broswer.execute_script("window.stop()")
至此,加载完整页面缓慢的问题解决。
3.2,base64字符串的获取和格式转码
问题1
解析获取页面中的img标签的src属性值。src值其格式为:
data:image/jpg;base64,base64字符串
base64,
后面的字符串才是要转码的内容,解决方案1
直接使用python的str类split方法获取base64字符串:
# img_src : 使用bs4获取的img标签的src属性值 # base64str : 想要获取的base64字符串编码 base64str = img_src.split('base64,')[1]
问题2
Base64编码需要转码为二进制编码后才能写为png或jpg文件,
解决方案2
使用base64类的转码函数转码:
import base64# base64str 为获得的base64字符串 imgdata = base64.b64decode(base64str) # imgdata 为转码后的二进制编码with open(img_name + ".jpg",'wb') as f:f.write(imgdata)
3.3,一些页面不存在
问题
测试过程中,发现一些图片编号的页面不存在,这样会导致获取页面标题失败,抛出异常,导致程序停止运行。
解决方案
通过if语句判断是否能够加载:
title = soup.select('div[...] > div[class="title"]')if len(title) == 0:# 后续操作
3.4,部分照片无法加载
问题
一些照片无法加载,其对应的img标签src为加载时的标记图片的链接,无法正常解析,会导致抛出异常。
解决方案
尝试刷新页面,尝试若干次后直接放弃:
具体会牵涉到较多逻辑,可以直接参考后面的参考代码的
trytimes
变量相关操作。大致逻辑:
设置变量trytimes为页面刷新次数,初始值为0 当判断出现图片加载失败时将其加一 - 当某个页面爬取完成后将 trytimes 设为0 - 当 trytimes 大于设置的尝试次数后直接跳到下一个页面爬取,放弃爬取无法加载的图片。(该页面爬取成功的图片还是会保存,再次加载的图片会保存或覆盖)
4,参考代码
这里直接吧代码贴出来吧,代码风格可能不太标准,欢迎指正:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import time
import base64
import osdef get_url(index):base_url = 'https://XXX/img/' # 爬取的目标网站不变的部分url = base_url + str(index) # 网站拼接return url def get_broswer():path = "C:\Program Files\...\chrome.exe" # chrome 的可执行文件位置options = Options()# 无头浏览器效率更高# phantomjs 好像现在 selenium 已经不支持了# 只能使用Chrome浏览器的无头模式options.add_argument('--headless')options.add_argument('--disable-gpu')options.binary_location = path# 关闭线程阻塞desired_capabilities = DesiredCapabilities.CHROMEdesired_capabilities["pageLoadStrategy"] = "none"broswer = webdriver.Chrome(chrome_options=options,executable_path='chromedriver.exe',desired_capabilities=desired_capabilities)return broswerdef get_content(broswer,url):broswer.get(url)time.sleep(5)broswer.execute_script("window.stop()")content = broswer.page_sourcereturn contentdef get_imglist(content):soup = BeautifulSoup(content,'lxml')img_list = soup.select('div[class="..."] > img')return img_listdef get_base64(img):base64 = img.attrs.get('src')base64 = base64.split('base64,')if len(base64) == 1:return 'false'return base64[1]def save_img(base64str,foldname,num):# 解码图片imgdata = base64.b64decode(base64str)img_fold = "./img/"+foldname+"/"# 每个图集保存一个文件夹,如果文件夹不存在要创建文件夹,否则会报错if os.path.exists(img_fold) == False:os.mkdir(img_fold)#将图片保存为文件with open(img_fold+str(num)+".jpg",'wb') as f:f.write(imgdata)# 获取图集名称,方便命名文件夹
def get_title_name(cotent):soup = BeautifulSoup(content,'lxml')# 注意返回的是数组title = soup.select('div[class="content"] > div[class="title"]')if len(title) == 0:return 'false'title_name = title[0].get_text()return title_name# 主函数
if __name__ == '__main__':broswer = get_broswer()#for index in range(100,4,-1):# 2304index = 1000 # 开始页 >大endpage = 1 # 结束页 >小 倒序爬取trytimes = 0 # 图片加载失败尝试次数dif = 1 # 爬取图集编号间隔,方便多开爬取,因为还没有学python多线程,就只想到这个法子,不在意速度这个可以不管while index >= endpage:flag = 0if trytimes > 2:print('TRYOVER_%d' % index)index -= diftrytimes = 0continueurl = get_url(index)content = get_content(broswer,url)img_list = get_imglist(content)foldname = get_title_name(content)if foldname == 'false':trytimes += 1print('NOTFOUND_%d' % (index))continuefor i in range(len(img_list)):img = img_list[i] base64str = get_base64(img) if base64str == 'false':# print('ERROLOAD_%d_%d' % (index,i))print('ERROLOAD_%d' % (index))flag = 1continuesave_img(base64str,foldname,i+1)if flag == 0:print('SUCCESS_%d_%s √' % (index,foldname))index -= diftrytimes = 0if flag == 1:trytimes += 1print('OVER')
总之最后效果还是比较理想的,最后成功爬取了想要的图片:
【爬虫】Selenium爬取动态网页的base64图片相关推荐
- Python之网络爬虫(selenium爬取动态网页、爬虫案例分析、哈希算法与RSA加密)
文章目录 一.selenium爬取动态网页 二.爬虫案例分析 三.哈希hash算法与RSA加密 一.selenium爬取动态网页 1.动态网页认知 爬虫其实就是在模仿浏览器的行为 应对要多次数据的交互 ...
- 用python爬取动态网页上的图片(百度图片)
用python爬取动态网页上的图片(百度图片) 参考B站一个视频,视频链接: https://www.bilibili.com/video/BV1Va4y1Y7fK?share_source=copy ...
- python爬虫使用selenium爬取动态网页信息——以智联招聘网站为例
python版本3.6 #导入两个模块 from selenium import webdriver import time from openpyxl import Workbook import ...
- python爬虫:爬取动态网页并将信息存入MySQL数据库
目标网站 http://www.neeq.com.cn/disclosure/supervise.html 爬取网页该部分内容 网页分析 查看网页源代码发现没有表格部分内容,对网页请求进行分析 F12 ...
- python爬取动态网页图片_python爬虫之爬取动态加载的图片_百度
运行坏境 python3.x 选择目标--百度 当我们在使用右键查看网页源码时,出来的却是一大堆JavaScript代码,并没有图片的链接等信息 因为它是一个动态页面嘛.它的网页原始数据其实是没有这个 ...
- Scrapy+Selenium爬取动态网页:no ‘moz:firefoxOptions.binary‘ capability provided
报错信息:selenium.common.exceptions.SessionNotCreatedException: Message: Expected browser binary locatio ...
- chrome动态ip python_用Python爬虫爬取动态网页,附带完整代码,有错误欢迎指出!...
系统环境: 操作系统:Windows8.1专业版 64bit Python:anaconda.Python2.7 Python modules:requests.random.json Backgro ...
- Python爬虫爬取动态网页
系统环境: 操作系统:Windows8.1专业版 64bit Python:anaconda.Python2.7 Python modules:requests.random.json Backgro ...
- python爬虫动态加载页面_Python+Selenium爬取动态加载页面(2)
注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...
最新文章
- 为什么编码不同会出现乱码?
- 武汉工程大学计算机学院吴云韬,吴兴隆-武汉工程大学计算机科学与工程学院...
- Mysql实现主从复制(一主双从)
- 这 30 个常用的 Maven 命令你必须熟悉
- 恋舞服务器维修,2144《梦幻恋舞》关闭充值及关服公告
- SLAM Cartographer(13)基于Ceres库的扫描匹配器
- 单片机片外程序存储器数据存储器操作命令
- JVM 内存设置大小
- 川菜中,你觉得哪道菜能称为“经典之菜”呢?
- 设计一个简单的家乡网站
- 单片机ADC0808,DAC0832信号发生器
- 分享使用ASO提升App Store排名的技巧,appstore排名优化
- CyanogenMod精简手记
- 关于字符串赋值的方法以及注意事项
- smss.exe之wom毒
- linux php启动端口,linux中如何开放指定端口
- 双拼、kotlin、依赖倒置
- 稿费一般多少钱一千字_编写教材的稿费一般是多少
- Exception in thread' main” java. 1ang. Runt imeException: Error while running command to get file pe
- 201671010412 郭佳 实验三 作业互评与改进