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条评论!