java函数计算使用ChromeDriver+headless(阿里云)

1、安装

chromedriver下载地址:http://chromedriver.storage.googleapis.com/index.html 

chrome下载地址:https://www.chrome64bit.com/index.php/chrome-64-bit-installer

2、maven依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.1.34</version>
</dependency>
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-chrome-driver</artifactId>
    <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-support</artifactId>
    <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>22.0</version>
</dependency>

3、阿里函数计算配置

在沙盒环境安装chrome,并记录缺少的依赖库:

先下载阿里函数计算命令行工具fcli,然后进行以下操作:

flci shell
sbox -d code -t java8
apt update
curl -L http://file.webx.xin/linux/google-chrome-stable_current_amd64.deb --output chrome
dpkg -i chrome
#在错误信息中拷贝出依赖库名称,执行以下命令安装

apt install fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatspi2.0-0 libgtk-3-0 libxss1 lsb-release wget xdg-utils
#若出现错误,执行以下命令

apt --fix-broken install #执行完不要急着按enter,把“The following additional packages will be installed:“后面的信息拷贝出来

#检查是否安装成功,如果打印出html源码了就ok
google-chrome --headless --disable-gpu --no-sandbox --dump-dom http://www.webx.xin

把以上操作中的"The following additional packages will be installed:"后面的依赖库写到以下文件中

fun.yml

runtime: java8
tasks:
  - shell: apt-get update
  - shell: mkdir -p /code/.fun/tmp/archives/
  - shell: apt install -y -d -o=dir::cache=/code/.fun/tmp adwaita-icon-theme at-spi2-core dconf-gsettings-backend dconf-service distro-info-data fonts-liberation  glib-networking glib-networking-common glib-networking-services gsettings-desktop-schemas libappindicator3-1  libasound2 libasound2-data libatk-bridge2.0-0 libatspi2.0-0 libauthen-sasl-perl libcolord2 libdbusmenu-glib4  libdbusmenu-gtk3-4 libdconf1 libegl1-mesa libencode-locale-perl libepoxy0 libfile-basedir-perl  libfile-desktopentry-perl libfile-listing-perl libfile-mimeinfo-perl libfont-afm-perl libfontenc1 libgbm1 libgtk-3-0  libgtk-3-bin libgtk-3-common libhtml-form-perl libhtml-format-perl libhtml-parser-perl libhtml-tagset-perl  libhtml-tree-perl libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl libhttp-message-perl  libhttp-negotiate-perl libindicator3-7 libio-html-perl libio-socket-ssl-perl libipc-system-simple-perl  libjson-glib-1.0-0 libjson-glib-1.0-common liblwp-mediatypes-perl liblwp-protocol-https-perl libmailtools-perl  libnet-dbus-perl libnet-http-perl libnet-smtp-ssl-perl libnet-ssleay-perl libproxy1v5 librest-0.7-0  libsoup-gnome2.4-1 libsoup2.4-1 libtext-iconv-perl libtie-ixhash-perl liburi-perl libwayland-client0  libwayland-cursor0 libwayland-egl1-mesa libwayland-server0 libwww-perl libwww-robotrules-perl libx11-protocol-perl  libxaw7 libxcb-shape0 libxcb-xfixes0 libxkbcommon0 libxml-parser-perl libxml-twig-perl libxml-xpathengine-perl  libxmu6 libxmuu1 libxpm4 libxss1 libxt6 libxv1 libxxf86dga1 lsb-release perl-openssl-defaults wget x11-utils  x11-xserver-utils xdg-utils xkb-data
  - shell: for f in $(ls /code/.fun/tmp/archives/*.deb); do dpkg -x $f /code/.fun/root; done;
  - shell: curl -L http://webxxx.oss-cn-beijing.aliyuncs.com/google-chrome-stable_current_amd64.deb --output /code/.fun/tmp/archives/chrome.deb
  - shell: dpkg -x /code/.fun/tmp/archives/chrome.deb /code/.fun/root
  - shell: rm -rf /code/.fun/tmp/archives
  - shell: curl -L http://webxxx.oss-cn-beijing.aliyuncs.com/chromedriver --output /code/.fun/root/sbin/chromedriver
  - shell: chmod +x /code/.fun/root/sbin/chromedriver

template.yml

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  chrome:
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'withdraw'
      LogConfig:
        Project: 'ybejia-fc-log'
        Logstore: 'internal-operation_log'
      VpcConfig:
        VpcId: 'vpc-xxx'
        VSwitchIds: [ 'vsw-xxx' ]
        SecurityGroupId: 'sg-xxx'
      NasConfig:
        UserId: 1000
        GroupId: 1000
        MountPoints:
          - ServerAddr: 'xxx.cn-beijing.nas.aliyuncs.com:/'
            MountDir: '/mnt/fun'
    withdraw:
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: com.ybejia.vo.WithdrawHandler::handleRequest
        Runtime: java8
        Timeout: 60
        MemorySize: 256
        CodeUri: './withdraw-1.0-SNAPSHOT-jar-with-dependencies.jar'
        EnvironmentVariables:
         'LD_LIBRARY_PATH': '/mnt/fun/.fun/root/usr/lib:/mnt/fun/.fun/root/usr/lib/x86_64-linux-gnu'
         'PATH': '/mnt/fun/.fun/root/opt/google/chrome:/mnt/fun/.fun/root/usr/local/bin:/mnt/fun/.fun/root/usr/local/sbin:/mnt/fun/.fun/root/usr/bin:/mnt/fun/.fun/root/usr/sbin:/mnt/fun/.fun/root/sbin:/mnt/fun/.fun/root/bin'

4、java代码(模拟提现)

package com.ybejia.vo;

import com.alibaba.fastjson.JSON;
import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.FunctionComputeLogger;
import com.aliyun.fc.runtime.StreamRequestHandler;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * xx提现函数
 */
public class WithdrawHandler implements StreamRequestHandler {

    @Override
    public void handleRequest(
            InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        try {
            ApiResponse resp = new ApiResponse();
            FunctionComputeLogger logger = context.getLogger();

            //获取请求数据
            StringBuffer lines = new StringBuffer();
            String line = null;
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            while ((line = bufferedReader.readLine()) != null) {
                lines.append(line);
            }
            logger.info("请求数据:" + lines);

            Map<String, Object> body = new HashMap<>();
            body.put("status", false);//默认结果为false

            ApiRequest request = JSON.parseObject(lines.toString(), ApiRequest.class);

            //参数为空的直接响应错误
            if (request.getQueryParameters() == null) {
                body.put("msg", "parameter为空");
                resp.setBody(JSON.toJSONString(body));
                resp.setStatusCode(200);
                outputStream.write(JSON.toJSONString(resp).getBytes());
                return;
            }

            //如果test为true就走测试
            String test = (String) request.getQueryParameters().get("test");
            if (test != null && "true".equals(test)) {
                baidu(logger, request, body);
            } else {
                withdraw(logger, request, body);
            }
            resp.setBody(JSON.toJSONString(body));
            resp.setStatusCode(200);
            outputStream.write(JSON.toJSONString(resp).getBytes());
        } catch (Exception e) {
            //响应异常结果
            ApiResponse resp = new ApiResponse();
            Map<String, Object> body = new HashMap<>();
            body.put("status", false);
            body.put("msg", e.getMessage());
            resp.setBody(JSON.toJSONString(body));
            resp.setStatusCode(200);
            outputStream.write(JSON.toJSONString(resp).getBytes());
        }
    }

    /**
     * 测试,用百度搜索java
     */
    public void baidu(FunctionComputeLogger log, ApiRequest request, Map<String, Object> body) {
        String url = (String) request.getQueryParameters().get("url");
        if (url == null) {
            body.put("msg", "url为空");
            return;
        }
        ChromeDriver webDriver = null;
        try {
            webDriver = getChromeDriver();
            //设置延时操作
            webDriver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);//-----页面加载时间
            //webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);//------元素等待时间(隐式等待)
            //webDriver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);//----脚本执行时间
            webDriver.get(url);

            WebElement kw = findElement(webDriver, By.id("kw"), 2);
            kw.sendKeys("java");

            webDriver.findElement(By.id("su")).click();

            WebElement contentLeft = findElement(webDriver, By.id("content_left"), 2);


            List<WebElement> titles = contentLeft.findElements(By.className("t"));
            StringBuilder sb = new StringBuilder(webDriver.getSessionId().toString());
            sb.append("--");
            for (WebElement title : titles) {
                sb.append(title.getText()).append(",");
            }
            body.put("status", true);
            body.put("msg", sb.toString());
        } catch (Exception e) {
            log.info("错误" + e);
            body.put("msg", e.getMessage());
        } finally {
            if (webDriver != null) {
                webDriver.quit();
            }
        }
    }

    /**
     * 获取chromeDriver
     */
    private ChromeDriver getChromeDriver() {
        String DRIVER_PATH = "/mnt/fun/.fun/root/sbin/chromedriver";

    System.setProperty("webdriver.chrome.driver",DRIVER_PATH);

ChromeOptions options = new ChromeOptions(); options.addArguments("--test-type"); //ignore certificate errors options.addArguments("--headless");// headless mode options.addArguments("--disable-gpu"); options.addArguments("--no-sandbox"); options.addArguments("--disable-dev-shm-usage"); options.addArguments("--disable-infobars"); options.addArguments("--disable-extensions"); options.addArguments("--disable-browser-side-navigation"); options.addArguments("--window-position=0,0");//指定窗口坐标 options.addArguments("--window-size=1903,1600");//指定窗口大小 options.setExperimentalOption("excludeSwitches", Arrays.asList("enable-automation", "ignore-certificate-errors")); return new ChromeDriver(options); } /** * 提现 */ public void withdraw(FunctionComputeLogger log, ApiRequest request, Map<String, Object> body) { String url = (String) request.getQueryParameters().get("url"); if (url == null) { body.put("msg", "url为空"); return; } String pwd = (String) request.getQueryParameters().get("pwd"); if (pwd == null) { body.put("msg", "密码为空"); return; } ChromeDriver webDriver = null; try { webDriver = getChromeDriver(); //设置延时操作 webDriver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);//-----页面加载时间 //webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);//------元素等待时间(隐式等待) //webDriver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);//----脚本执行时间 webDriver.get(url); WebElement password = findElement(webDriver, By.id("password"), 2); if (password != null) { password.sendKeys(pwd); webDriver.findElement(By.id("nextButton")).click(); WebElement inpPrompt = findElement(webDriver, By.className("inpPrompt"), 2); if (inpPrompt != null) { String text = inpPrompt.getText(); log.info(text); body.put("msg", text); return; } body.put("status", true); log.info("成功响应:" + webDriver.getPageSource()); return; } else { By errorTitleBy = By.className("errorTitle"); WebElement errorTitle = findElement(webDriver, errorTitleBy, 2); if (errorTitle != null) { String err = errorTitle.getText(); log.info(err); body.put("msg", err); return; } } log.info("错误页面:" + webDriver.getPageSource()); body.put("msg", "未知错误,请联系技术"); } catch (Exception e) { log.warn("错误:" + e.getMessage()); body.put("msg", e.getMessage()); } finally { if (webDriver != null) { webDriver.quit(); } } } /** * 查询页面元素 */ public WebElement findElement(WebDriver webDriver, By by, int waitSeconds) { try { WebDriverWait wait = new WebDriverWait(webDriver, waitSeconds); wait.until(ExpectedConditions.visibilityOfElementLocated(by)); return webDriver.findElement(by); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 查询页面元素 */ public WebElement findElement(WebDriver webDriver, By by) { try { return webDriver.findElement(by); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 执行本地命令 */ public void exec(String command, FunctionComputeLogger log) throws IOException { Runtime runtime = Runtime.getRuntime(); Process exec = runtime.exec(command); BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getErrorStream())); String line = null; while ((line = reader.readLine()) != null) { log.info(line); } reader = new BufferedReader(new InputStreamReader(exec.getInputStream())); while ((line = reader.readLine()) != null) { log.info(line); } } }

部署函数:

配置fun参数: 

fun config 
#然后按照提示,依次配置 Account ID、Access Key Id、Secret Access Key、 Default Region Name 即可

1、打包代码 mvn package

2、安装函数相关依赖 fun install,执行后在.fun目录生成相关系统依赖库文件

3、上传依赖库到nas

fun nas init 

cp -r .fun/root .fun/xxx.nas.aliyuncs.com 

fun nas sync

fun nas ls nas://xxx:/mnt/fun/ #查看nas中已上传的文件

4、部署函数 fun deploy

本地调试函数:fun local invoke xxx

2019-08-15 00:48:19

共有0条评论!

发表评论