• 文章简介
    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图片相关推荐

  1. Python之网络爬虫(selenium爬取动态网页、爬虫案例分析、哈希算法与RSA加密)

    文章目录 一.selenium爬取动态网页 二.爬虫案例分析 三.哈希hash算法与RSA加密 一.selenium爬取动态网页 1.动态网页认知 爬虫其实就是在模仿浏览器的行为 应对要多次数据的交互 ...

  2. 用python爬取动态网页上的图片(百度图片)

    用python爬取动态网页上的图片(百度图片) 参考B站一个视频,视频链接: https://www.bilibili.com/video/BV1Va4y1Y7fK?share_source=copy ...

  3. python爬虫使用selenium爬取动态网页信息——以智联招聘网站为例

    python版本3.6 #导入两个模块 from selenium import webdriver import time from openpyxl import Workbook import ...

  4. python爬虫:爬取动态网页并将信息存入MySQL数据库

    目标网站 http://www.neeq.com.cn/disclosure/supervise.html 爬取网页该部分内容 网页分析 查看网页源代码发现没有表格部分内容,对网页请求进行分析 F12 ...

  5. python爬取动态网页图片_python爬虫之爬取动态加载的图片_百度

    运行坏境 python3.x 选择目标--百度 当我们在使用右键查看网页源码时,出来的却是一大堆JavaScript代码,并没有图片的链接等信息 因为它是一个动态页面嘛.它的网页原始数据其实是没有这个 ...

  6. Scrapy+Selenium爬取动态网页:no ‘moz:firefoxOptions.binary‘ capability provided

    报错信息:selenium.common.exceptions.SessionNotCreatedException: Message: Expected browser binary locatio ...

  7. chrome动态ip python_用Python爬虫爬取动态网页,附带完整代码,有错误欢迎指出!...

    系统环境: 操作系统:Windows8.1专业版 64bit Python:anaconda.Python2.7 Python modules:requests.random.json Backgro ...

  8. Python爬虫爬取动态网页

    系统环境: 操作系统:Windows8.1专业版 64bit Python:anaconda.Python2.7 Python modules:requests.random.json Backgro ...

  9. python爬虫动态加载页面_Python+Selenium爬取动态加载页面(2)

    注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...

最新文章

  1. 为什么编码不同会出现乱码?
  2. 武汉工程大学计算机学院吴云韬,吴兴隆-武汉工程大学计算机科学与工程学院...
  3. Mysql实现主从复制(一主双从)
  4. 这 30 个常用的 Maven 命令你必须熟悉
  5. 恋舞服务器维修,2144《梦幻恋舞》关闭充值及关服公告
  6. SLAM Cartographer(13)基于Ceres库的扫描匹配器
  7. 单片机片外程序存储器数据存储器操作命令
  8. JVM 内存设置大小
  9. 川菜中,你觉得哪道菜能称为“经典之菜”呢?
  10. 设计一个简单的家乡网站
  11. 单片机ADC0808,DAC0832信号发生器
  12. 分享使用ASO提升App Store排名的技巧,appstore排名优化
  13. CyanogenMod精简手记
  14. 关于字符串赋值的方法以及注意事项
  15. smss.exe之wom毒
  16. linux php启动端口,linux中如何开放指定端口
  17. 双拼、kotlin、依赖倒置
  18. 稿费一般多少钱一千字_编写教材的稿费一般是多少
  19. Exception in thread' main” java. 1ang. Runt imeException: Error while running command to get file pe
  20. 201671010412 郭佳 实验三 作业互评与改进

热门文章

  1. 触摸屏技术属于计算机技术中的什么,触摸屏技术
  2. java date是cst_Java CST 日期问题
  3. Latex texstudio+ctex中文解决方案
  4. 【midomi】Android下最强音乐搜索工具
  5. BBS系统的设计与实现
  6. mcnpf5输出结果_MCNP入门教程
  7. 网页突然报502 bad gateway,平台宕掉
  8. 万字长文---手把手教你加固内核安全配置
  9. 写一个Linux下搭建Discuz论坛的全过程教程。
  10. 主成分分析与其在人脸识别中的应用