Selenium 使用实例,爬取图片、浏览器截长图

Selenium 使用实例,爬取图片、浏览器截长图

Selenium 使用实例

翻页爬取图片

  • 需要用到的模块

    from selenium import webdriver   #浏览器驱动
    from selenium.webdriver.chrome.options import Options #设置
    # 其他模块
    import time
    import ssl
    import threading        #多线程下载
    import urllib.request   #下载
    import urllib.error     #下载
    
  • 携带配置、创建浏览器。

    def browser_get():
        # 创建设置对象
        chrome_options = Options()  
        # 向对象添加参数,手机模式。
        chrome_options.add_experimental_option("mobileEmulation", { "deviceName": "Nexus 5" })
        # 向设置添加headless模式。
        chrome_options.add_argument('--headless')
        # 设置驱动位置、传入设置对象
        browser = webdriver.Chrome(r'F:\study_project\webpack\SeleniumDemo\chromedriver.exe',chrome_options = chrome_options)
        # 打开url
        browser.get('http://jandan.net/ooxx')
        # 设置等待时间。
        browser.implicitly_wait(10)
    
  • 重要 设置页面滚动参数,让页面加载完全才能取得到xpath。

    def browser_get():
        ... ...
        js="document.documentElement.scrollTop="+ str(500)
        browser.execute_script(js)
        time.sleep(2)
    
  • 取到资源列表。这里最好直接取到全部目标元素。否则会出现意外bug。download_pic是下载方法,给他传入图像url就能实现下载。

    def browser_get():
        ... ...
        # 假设这些元素携带了图片url地址。
        ul = browser.find_elements_by_xpath('//a[@class="view_img_link"]')
        # 我们采用多线程来下载图片。
        for li in ul:
            threading.Thread(target=download_pic,args=(li.get_attribute("href"),)).start()
        # 我们第一页内容已经下载完了,我们需要进入循环来下载页面内容了。下载完第一页,执行request_start函数。
        request_start(browser,base_url)
    
  • 进入翻页循环。

    def request_start(browser,base_url):
        # 我们在每页都需要滚动页面到下面来完成js渲染。
        js="document.documentElement.scrollTop="+ str(8000)
        browser.execute_script(js)
        time.sleep(2)
        browser.implicitly_wait(10)
        # 在这里找到翻页元素调用其点击。
        element=browser.find_element_by_xpath('//a[@title="Older Comments"][1]')
        print('text--------{}'.format(element.text))
        if element:
            # 如果存在就点击下一页。给一个反应时间。慢一点...
            element.click()
            time.sleep(10)
        # 和上面一样,继续找到页面所有携带图片url的元素
        ul = browser.find_elements_by_xpath('//a[@class="view_img_link"]')
        for li in ul:
            threading.Thread(target=download_pic,args=(li.get_attribute("href"),)).start()
        if ul:
            #如果ul存在就不停的爬取。
            return request_start(browser,base_url)
    
  • 下载图片的方法

    # 下载图片
    def download_pic(url):
        correct_url = url
        if url.startswith('//'):
            correct_url = url[2:]
        if not url.startswith('http'):
            correct_url = 'http://' + correct_url
        print(correct_url)
        headers = {
            'Host': 'wx2.sinaimg.cn',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/61.0.3163.100 Safari/537.36 '
        }
        try:
            req = urllib.request.Request(correct_url, headers=headers)
            resp = urllib.request.urlopen(req)
            pic = resp.read()
            pic_name = correct_url.split("/")[-1]
            with open(pic_save_path + pic_name, "wb+") as f:
                f.write(pic)
        except (OSError, urllib.error.HTTPError, urllib.error.URLError, Exception) as reason:
            print(str(reason))
    
  • 设置ssl上下文、定义主函数。

    if __name__ == "__main__":
        ssl._create_default_https_context = ssl._create_unverified_context
        browser_get()
    
  • 总结,用到的关键语句。

    browser
    .implicitly_wait(10)        #设置等待超时
    .find_elements_by_xpath()   #返回列表
    .find_element_by_xpath()    #返回单个
    .execute_script(js)         #执行js
    .add_experimental_option()  #添加设置
    
    js="document.documentElement.scrollTop="+ str(500)  #页面滚动的js语句。
    
    threading.Thread(target=fun,args=(**kwargs,)).start() #多线程
    

滚动截取网页

  • 首先要知道如何进行页面滚动。例如我们用手机模式访问站点。那么我们需要知道手机高度pix_h=640
  1. 向浏览器发送js可执行脚本把滚动条下拉64,js="document.documentElement.scrollTop="+ str(i*pix_h)
  2. 截图并获取滚动条当前状态。"return document.documentElement.scrollHeight.toString()+','+document.documentElement.scrollTop.toString()"
  3. 判断底部高度是否没有变化,没有证明到底了。有就继续执行操作2。
  4. 对于滚动加载的页面需要判断是否需要再次加载。这时就要等待一下继续判断。如果仍没有,就的确到底了。还要给循环加上最大次数。
  • 引用的包

    # selenium
    from selenium import  webdriver
    from selenium.webdriver.chrome.options import Options
    #一些系统和文件操作用于合并
    import time
    import os
    from PIL import Image
    
  • 封装这个函数。有些页面你需要点确定/关闭才能浏览,我们需要操作一下让浏览器自动点确定,只需要输入关闭按钮xpathnotify。其中一部分准备。真正的循环结构下面说明。

    def url_captrue(url_path='https://guazi.com/bj/buy/',pix_h=640,headless=True,deviceName="Nexus 5",exePath='F:\study_project\webpack\SeleniumDemo\chromedriver.exe',notify='/html/body/div[5]/div[2]/div/img'):
        """垂直合并多张图片 
        url_path - 打开的页面
        pix_h - 手机高度。
        headless - 是否使用无图模式
        deviceName - 如果是手机,请设置设备名称。如果是浏览器请写deviceName=''
        exePath - 驱动文件位置。
        notify - 首页是否有通知,默认有。如无填写notify=''
        """ 
        
        #创建浏览器设置
        chrome_options = Options()
        headlessflag=lambda x: '--headless' if x==True else ''
        if headless:
            chrome_options.add_argument(headlessflag(headless))
    
        #添加设备参数
        if deviceName!='' or deviceName!="" or deviceName!=None:
            chrome_options.add_experimental_option("mobileEmulation", { "deviceName": deviceName })
    
        #启动浏览器
        wd = webdriver.Chrome(exePath,chrome_options = chrome_options)
        wd.get(url_path)
    
        #检测首页通知参数
        wd.implicitly_wait(10)
        if notify!='' or notify!="" or notify!=None:
            wd.find_element_by_xpath(notify).click()
    
  • 循环结构。这就刚才提到的几步。

    def url_captrue(url_path='https://guazi.com/bj/buy/',pix_h=640,headless=True,deviceName="Nexus 5",exePath='F:\study_project\webpack\SeleniumDemo\chromedriver.exe',notify='/html/body/div[5]/div[2]/div/img'):
        ... ...(继承上面代码)
        i=0
        img_list = []
        while i<8:
            js="document.documentElement.scrollTop="+ str(i*pix_h)+";"
            wd.execute_script(js)
            js1 = "return document.documentElement.scrollHeight.toString()+','+document.documentElement.scrollTop.toString()"
            js1_result = wd.execute_script(js1)
            real_scroll_h, real_top = js1_result.split(',')[0], js1_result.split(',')[1]
            print('{}-----{}'.format(real_scroll_h,real_top))
    
            if real_top == str(i*pix_h):    # 当前滚动条位置是都等于预期位置。是就截图
                i += 1
                #wd.save_screenshot('static/capture/wap/wap-'+filename + str(i)+'.png')
                wd.get_screenshot_as_file('imgcontent\{}.png'.format(i))
                img_list.append('imgcontent\{}.png'.format(i))
                last_t = real_top
            else:
                # 如果本次设置失败,看这次的top和上一次记录的top值是否相等,相等则说明没有新加载内容,且已到页面底,跳出循环
                if real_top != last_t:      # 当前滚动条不等于本次预期位置。也不是上次预期位置,进入下次循环截图。
                    last_t = real_top
                    time.sleep(5)           # 这里需要等待一下,对于滚动页面。看看还有没有加载。
                    print('加载一次')
                else:                  # 当前滚动条不等于本次预期位置,而是上次预期位置。直接退出
                    #wd.get_screenshot_as_file('imgcontent\{}.png'.format(i))
                    #img_list.append('imgcontent\{}.png'.format(i))
                    break
        image_merge(img_list, r'F:\study_project\webpack\SeleniumDemo\02SeleniumHeaderLess', 'all.png')
    
  • 合并图像的代码:

    def image_merge(images, output_dir, output_name='merge.jpg', restriction_max_width=None, restriction_max_height=None):  
    
        """垂直合并多张图片 
        images - 要合并的图片路径列表 
        ouput_dir - 输出路径 
        output_name - 输出文件名 
        restriction_max_width - 限制合并后的图片最大宽度,如果超过将等比缩小 
        restriction_max_height - 限制合并后的图片最大高度,如果超过将等比缩小 
        """  
        def image_resize(img, size=(1500, 1100)):  
            """调整图片大小 
            """  
            try:  
                if img.mode not in ('L', 'RGB'):  
                    img = img.convert('RGB')  
                img = img.resize(size)  
            except Exception(e):  
                pass  
            return img 
        max_width = 0  
        total_height = 0  
        # 计算合成后图片的宽度(以最宽的为准)和高度  
        for img_path in images:  
            if os.path.exists(img_path):  
                img = Image.open(img_path)  
                width, height = img.size  
                if width > max_width:  
                    max_width = width  
                total_height += height  
      
        # 产生一张空白图  
        new_img = Image.new('RGB', (max_width, total_height), 255)  
        # 合并  
        x = y = 0  
        for img_path in images:  
            if os.path.exists(img_path):  
                img = Image.open(img_path)  
                width, height = img.size  
                new_img.paste(img, (x, y))  
                y += height  
      
        if restriction_max_width and max_width >= restriction_max_width:  
            # 如果宽带超过限制  
            # 等比例缩小  
            ratio = restriction_max_height / float(max_width)  
            max_width = restriction_max_width  
            total_height = int(total_height * ratio)  
            new_img = image_resize(new_img, size=(max_width, total_height))  
      
        if restriction_max_height and total_height >= restriction_max_height:  
            # 如果高度超过限制  
            # 等比例缩小  
            ratio = restriction_max_height / float(total_height)  
            max_width = int(max_width * ratio)  
            total_height = restriction_max_height  
            new_img = image_resize(new_img, size=(max_width, total_height))  
          
        if not os.path.exists(output_dir):  
            os.makedirs(output_dir)  
        save_path = '%s/%s' % (output_dir, output_name)  
        new_img.save(save_path)  
        return save_path
    
  • 编写主函数测试一下

    if __name__ == "__main__":
        url_captrue()
    
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值