java selenium div embedded scrollbar page long screenshot to send mail

java selenium web page embedded scrollbar screenshot to send mail


Because the company requires an interface, requesting this interface for web page screenshots and sending mail function, originally written in python, but does not seem to meet the requirements, then use java to rewrite, although I am a Java vegetable chicken, but this does not affect my patching, ctrl c and ctrl v v.

Main problems

This requirement is very simple, mainly is the screenshot of the web page. If the web page has its own scrollbar with browser, then a command of selenium can solve the screenshot of the whole web page, but the goose is a pit, and its scrollbars are embedded in the div element, so we need to calculate the height of the div element, scroll the screenshot, and then scroll out. The screenshots are stitched together.
As shown in the figure, this thing is divided into several parts.
Left function bar (omitted in screenshots)
Top function bar (it's impossible to take a screenshot of the top every time you scroll, so I chose to take a screenshot of the top first, and then take a screenshot of the main content of the page scroll bar)
The main scrollbar of the web page (of course, this scrollbar belongs to that very disgusting div element)

It's clear that this is the thing. Therefore, it is ineffective to get the height of the browser or window. We must first get the height of the div scrollbar, just like this:

document.getElementsByClassName('scroll-canvas scroll-canvas--dashboard')[0].scrollHeight

Let's start with the following

    private void getGrafana(String username, String password, String url,
                            String mailUser, String mailPassword, String[] mailReceiver, String mailServer) {
        WebDriver driver=null;
        // Define the image name
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String  file_name = "sendmail_" + sdf.format(d) + ".png";
        try {
        	//If you write it yourself, call chrome driver directly here. I'm calling the encapsulation method here.
            driver = WebDriverUtil.getH5Driver();
            driver.get(url);
            driver.manage().timeouts().implicitlyWait(20,TimeUnit.SECONDS);
            System.out.println("Wait for loading after opening the web address");
            // User name
            By loc  = By.xpath("//input[@id='username']");
            WebElement ele1 = WebDriverUtil.find_element(driver, loc, 1,10);
            ele1.click();
            ele1.clear();
            ele1.sendKeys(username);
            //Password
            loc = By.xpath("//input[@id='password']");
            WebElement ele2 = WebDriverUtil.find_element(driver, loc, 1, 10);
            ele2.click();
            ele2.clear();
            ele2.sendKeys(password);
            //Click login
            loc = By.xpath("//input[@name='submit']");
            WebElement ele3 = WebDriverUtil.find_element(driver, loc, 1, 10);
            ele3.click();
            Thread.sleep(8000);
            if(driver.getTitle() != null && driver.getTitle().length() >0){
                System.out.println("It opens:" +driver.getTitle());
            }else{
                System.out.println("No page opened, please check!");
            }
            try {
                long scroll_width = (long) ((JavascriptExecutor)driver).executeScript("return document.body.parentNode.scrollWidth;");
                long scroll_height = (long) ((JavascriptExecutor)driver).executeScript("return document.body.offsetHeight;");
                //System.out.println(scroll_width + scroll_height);
                driver.manage().window().setSize(new Dimension((int)scroll_width, (int) scroll_height));
                String js_scroll = "document.getElementsByClassName('scroll-canvas scroll-canvas--dashboard')[0].scrollTop =";
                int content_height = (int)(long) ((JavascriptExecutor)driver).executeScript("return document.getElementsByClassName('scroll-canvas scroll-canvas--dashboard')[0].scrollHeight");
                int title_height = (int)(long) ((JavascriptExecutor)driver).executeScript("return document.getElementsByClassName('navbar')[0].offsetHeight");
                System.out.println("content height is: " + content_height + ", title height is: " + title_height);
                WebElement scroll_content = driver.findElement(By.xpath("//div[@class='scroll-canvas scroll-canvas--dashboard']"));
                WebElement scroll_top = driver.findElement(By.xpath("//div[@class='navbar']"));
                Thread.sleep(2000);
                boolean flag = GrafanaSendScreenShot.fullpage_screenshot(driver, file_name, title_height,  content_height, js_scroll, scroll_top, scroll_content);
            }catch (Exception e){
                e.printStackTrace();
                System.out.println("Failed to calculate browser height width or screenshot, please check");
                System.out.println(e.getMessage());
                Reporter.log(e.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("There is a problem loading the web page. Please check it.");
            System.out.println(e.getMessage());
            Reporter.log(e.getMessage());
        } finally {
            if(driver != null) {
                driver.close();
                driver.quit();
            }
        }
        File file = new File("");
        String baseDir = file.getAbsolutePath();
        String file_path = baseDir+"/screen/";
        File filetmps = new File(file_path+file_name);
        boolean flag = filetmps.exists();
        if (flag) {
            System.out.println("Use screenshot files: "+ filetmps.getName());
            try{
                System.out.println("Start sending mail...");
                GrafanaSendScreenShot.send_email(filetmps, mailUser, mailPassword, mailReceiver, mailServer);
                System.out.println("Successful mail delivery...");
            }catch (Exception e){
                e.printStackTrace();
                System.out.println(e.getMessage());
                Reporter.log(e.getMessage());
            }
        }else{
            System.out.println("The screenshot does not exist, please check or try again!");
        }

    }

Here we should pay attention to:
Mode 1:

JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
jsExecutor.executeScript("js Code");

Mode 2:

(JavascriptExecutor)driver).executeScript("js Code");


As a vegetable chicken, I really can't see the difference. In Mode 1, I returned null all the time, null until I suspected life. Mode 2 is feasible. I don't know what the big boys are like. If you know the trouble, let me know.

The following is the main code of the screenshot:

public class GrafanaSendScreenShot {

    public static boolean fullpage_screenshot(WebDriver driver, String file_pic, int title_height,
                                              int content_height, String js_scroll, WebElement scroll_top, WebElement scroll_content) throws InterruptedException, IOException {
        System.out.println("Starting chrome full page screenshot workaround ...");
        // Get information about the height and width of the browser scrollbar
        if (content_height == 0 ){
            content_height = (int)(long) ((JavascriptExecutor)driver).executeScript("return document.body.parentNode.scrollHeight");
        }
        int total_width = (int)(long) ((JavascriptExecutor)driver).executeScript("return document.body.offsetWidth");
        int total_height = content_height + title_height;
        int viewport_width =(int)(long) ((JavascriptExecutor)driver).executeScript("return document.body.clientWidth");
        int viewport_height = (int)(long) ((JavascriptExecutor)driver).executeScript("return window.innerHeight");
        System.out.println("Total: ("+total_width+ ","+total_height+")" + " Viewport: ("+viewport_width+","+viewport_height+")");
        List<List<Integer>> rectangles = new ArrayList<>();
        int i = 0;
        int count = 0;
        int top_height;
        int top_width;
        while(i<total_height){
            int ii = 0;
            if(count == 0){
                top_height = i + title_height;
            }else{
                top_height = i + viewport_height;
            }
            if(top_height > total_height){
                top_height = total_height;
            }
            while (ii < total_width){
                top_width = ii + viewport_width;
                if (top_width > total_width){
                    top_width = total_width;
                }
                System.out.println("Appending rectangle: "+ii+"  ,"+ i+"  ,"+ top_width+"  ,"+ top_height);
                List<Integer> tmp_data = new ArrayList<>();
                tmp_data.add(ii);
                tmp_data.add(i);
                tmp_data.add(top_width);
                tmp_data.add(top_height);
                rectangles.add(tmp_data);
                ii = ii + viewport_width;
            }
            if(count == 0){
                i = i + title_height;
            }else{
                i = i + viewport_height;
            }
            count = count +1;
        }
        //Make a brand new picture.~
        BufferedImage stitched_image = null;
        stitched_image = new BufferedImage(total_width, total_height, BufferedImage.TYPE_INT_RGB);
        List<Integer> previous = new ArrayList<>();
        int part = 0;
        int [] offset ;
        File file = new File("");
        //Using relative paths, place screenshots of intermediate processes and final files in the screen directory
        String baseDir = file.getAbsolutePath();
        String file_path = baseDir+"/screen/";
        System.out.println("pic tmp file path: " +file_path);
        //Once the screenshot has been cut and rolled
        for(List<Integer> rectangle:rectangles){
            if( previous.size()!=0 ){
                ((JavascriptExecutor)driver).executeScript(js_scroll+"("+ rectangle.get(0) +","+ rectangle.get(1) +" )");
                System.out.println("Scrolled To" +"("+ rectangle.get(0) +","+ rectangle.get(1) +" )");
                Thread.sleep(1000);
            }
            String file_name = "part_"+part+".png";
            System.out.println("Capturing..."+file_name);
            File filetmps = new File(file_path+file_name);
            //If part==0, the top function bar of the screenshot is actually a screenshot of scroll.
            if(part == 0){
                //OutputType.FILE is specified as a parameter passed to the getScreenshotAs() method, which means that the captured screen is returned as a file.
                File srcFile =  scroll_top.getScreenshotAs(OutputType.FILE);
                //Use the copyFile() method of the FileUtils tool class to save the file object returned by getScreenshotAs().
                FileUtils.copyFile(srcFile,filetmps);
                String jq1 = "$('.navbar').remove()";
                String jq2 = "$('.scroll-canvas--dashboard').css('height','100%')";
                ((JavascriptExecutor)driver).executeScript(jq1);
                System.out.println("Cancel the top bar display");
                ((JavascriptExecutor)driver).executeScript(jq2);
                System.out.println("Cancel bottom height bar display");
                Thread.sleep(1000);
            }else{
                File srcFile = scroll_content.getScreenshotAs(OutputType.FILE);
                FileUtils.copyFile(srcFile,filetmps);
                Thread.sleep(1000);
            }
            Image screenshot = ImageIO.read(new File(file_path+file_name));
            if (rectangle.get(1) + viewport_height > total_height) {
                offset = new int[]{rectangle.get(0), (total_height - viewport_height)};
            }else{
                offset = new int[]{rectangle.get(0), rectangle.get(1)};
            }
            System.out.println("Adding to stitched image with offset " +offset[0]+","+offset[1]);
            // Put the picture on the original map
            Graphics g =stitched_image.getGraphics();
            g.drawImage(screenshot,offset[0],offset[1],null);
            g.dispose();
            boolean flag = filetmps.exists();
            if (flag) {
                 System.out.println("tmp Pictures exist, delete");
                filetmps.delete();
            }else{
                System.out.println("tmp Pictures do not exist");
            }
            part = part + 1;
            previous = rectangle;
        }
        // Final generated picture
        ImageIO.write(stitched_image,"png", new File(file_path +file_pic));
        System.out.println("Finishing chrome full page screenshot workaround...");
        return true;
    }
	
	//This is to send mail. It's simple.
    public static void send_email(File file_name, String mailUser, String mailPassword, String[] mailReceiver, String mailServer)
            throws UnsupportedEncodingException, MessagingException {
        Date d = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Properties properties = new Properties();
        //1. Create mail objects
        properties.put("mail.smtp.host", mailServer);// Specify SMTP Server
        properties.put("mail.smtp.auth", "true"); // Specifies whether SMTP validation is required
        Session session = Session.getInstance(properties);
        MimeMessage message =new MimeMessage(session);
        //2. Setting up the sender
        // The three parameters of Internet Address are: mailbox, display nickname (for display only, no special requirements), character set encoding of nickname.
        message.setFrom(new InternetAddress(mailUser,mailUser,"UTF-8"));
        //3. Setting up multiple recipients
        //To Recipient CC Copy BCC Secret Delivery
        InternetAddress[] sendTo = new InternetAddress[mailReceiver.length];
        for (int i=0; i<mailReceiver.length; i++){
            System.out.println("Send to:"+ mailReceiver[i]);
            sendTo[i] = new InternetAddress(mailReceiver[i]);
        }
        message.setRecipients(MimeMessage.RecipientType.TO, sendTo);
        //Recipient's Single Manner
        //message.setRecipient(MimeMessage.RecipientType.TO,new InternetAddress(mailReceiver,"xin","UTF-8"));
        // message.addRecipient(MimeMessage.RecipientType.CC,new InternetAddress("409****1@qq.com","xinyuezi","UTF-8"));
        //4. Setting Themes
        message.setSubject("screenshot" ,"UTF-8");
        //message.setContent("Test Content: This is a test email...", "text/html;charset=UTF-8");

        //A Multipart object contains one or more body objects that form the body of the mail
        MimeMultipart multipart = new MimeMultipart();
        //Read local pictures and add image data to Node
        MimeBodyPart image = new MimeBodyPart();
        DataHandler dataHandler1 = new DataHandler(new FileDataSource(file_name));
        image.setDataHandler(dataHandler1);
        image.setContentID("image_screen");
        //Create text nodes
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("<font color=black>Screenshot time: "+sdf.format(d)+"<br></font><img src='cid:image_screen'/>","text/html;charset=UTF-8");

        // Appendix, not for the time being
        //Create attachment nodes to read local files and read attachment names
//        MimeBodyPart file1 = new MimeBodyPart();
//        DataHandler dataHandler2 = new DataHandler(new FileDataSource("C:\\Users\\Public\\Pictures\\Sample Pictures\\growing.png"));
//        file1.setDataHandler(dataHandler2);
//        file1.setFileName(MimeUtility.encodeText(dataHandler2.getName()));
//
//        MimeBodyPart file2 = new MimeBodyPart();
//        DataHandler dataHandler3 = new DataHandler(new FileDataSource("E:\\Tang\\topics.xlsx"));
//        file2.setDataHandler(dataHandler3);
//        file2.setFileName(MimeUtility.encodeText(dataHandler3.getName()));

        //Add text and images to multipart
        multipart.addBodyPart(text);
        multipart.addBodyPart(image);
        multipart.setSubType("mixed");//mixed relations
        message.setContent(multipart);
        message.saveChanges();
        Transport transport = session.getTransport("smtp");
        transport.connect(mailUser, mailPassword);
        transport.sendMessage(message,message.getAllRecipients());
        transport.close();
    }

}

Citation
1: https://www.cnblogs.com/MasterMonkInTemple/p/9970512.html
2: https://blog.csdn.net/xinyuezitang/article/details/85768462
3: https://www.cnblogs.com/chbyiming-bky/articles/8940105.html
4: https://www.iteye.com/blog/lijingshou-2019323

Tags: Session Java Selenium Python

Posted on Wed, 11 Sep 2019 01:35:17 -0700 by js_280