昨天突然有一个需求(自己的),想把某个网站题目主体部分翻译并保存成图片,开始时用了国内网站的翻译(人工、简单翻译),后来发现很多地方翻译的不尽人意,于是只好用翻译插件对原始网站进行翻译,插件会在每段后面插入翻译内容、设置使用背景色后显得不凌乱,效果还不错(至少尊重原文描述,保证了题意清晰)。本来想着爬取文本,然后做翻译什么的,但实际使用时需要仅允许使用一个网站,其他的都屏蔽掉,只好截图了。遇到几个问题,记录一下,有用到的拿走不谢:
〇、首先,你要NUGET这玩意和webdriver,然后导入它们
Imports OpenQA.Selenium
Imports OpenQA.Selenium.Chrome
一、官方文档,各种参数老全了List of Chromium Command Line Switches « Peter Beverloohttps://peter.sh/experiments/chromium-command-line-switches/二、带翻译的截图
开始说过,搞了一下有简单翻译的网页,直接截图就可以。但是,带有插件的就麻烦很多:
1、开启插件:可以加载指定扩展或者干脆加载用户设置
加载用户设置可以让我们直接使用设置好的chrome,非常方便:
options.AddArgument("--user-data-dir=C:/Users/Administrator/AppData/Local/Google/Chrome/User Data/")
2、开始整活
众所周知,一个自动化程序,弹出chrome就很low。于是,苦难开始了:
options.AddArguments("--headless")
似乎应该可以有效吧!确实有效,浏览器窗口没了,插件也跟着没了——即使你开启了插件的各种权限和自动翻译。折腾吧,改用以下语句:
options.AddArguments("--headless=new") '新无头模式可以正常加载插件
然后,加上各式各样的其他参数,就可以启动chromedriver.exe了:
If options Is Nothing Then
options = New ChromeOptions()
'加载用户配置。解决不加载插件的方法是让浏览器显示出来,然后重新安装一遍。。。。而后打开这个设置即可
options.AddArgument("--user-data-dir=C:/Users/Administrator/AppData/Local/Google/Chrome/User Data/")
'设置浏览器参数
options.AddArguments("--headless=new") '新无头模式可以正常加载插件
options.AddArguments("--no-sandbox")
options.AddArguments("--disable-gpu")
options.AddArguments("--disable-dev-shm-usage")
'单进程运行
'options.AddArgument("--single-process")
'固定端口
'options.AddArguments("--remote-debugging-port=13888")
End If
If driver Is Nothing Then driver = New ChromeDriver(options)
嘎嘎完美,如果按下葫芦瓢没飘起来——chromedriver.exe又出来整活了,这个命令行窗口还得藏起来。把搜索引擎搜索的直冒火星子之后,发现这么两句:
Dim service As ChromeDriverService = ChromeDriverService.CreateDefaultService()
service.HideCommandPromptWindow = True
这一看就顾名思义了,估摸搞定了!然并卵,这个语句创建了一个默认配置的服务,可是我们并没有用它啊,是不是赶脚少点啥,就像上了一天学都在神游回到家赶脚心里空落落的,酱紫:
If driver Is Nothing Then driver = New ChromeDriver(service, options)
至此,用之前爬取的题目列表继续爬原始网站,截图带翻译的题目即可。
driver.Navigate().GoToUrl(purl & pid)
Thread.Sleep(8000) '如果不需要翻译可以少一些
'把宽度设置成题目栏最大宽度
driver.Manage.Window.Size = New Size(1258, 1024)
Thread.Sleep(100) '如果不需要翻译可以少一些
'获取高度和宽度一定要在设置URL之后,不然会导致获取不到页面真实的宽高;
Dim Width As Integer = driver.ExecuteScript("return document.documentElement.scrollWidth")
Dim Height As Integer = driver.ExecuteScript("return document.body.parentNode.scrollHeight")
'设置宽高否则无法截全,这种模式必须运行在--headless下,否则窗体无法超过屏幕高度
driver.Manage.Window.Size = New Size(1258, Height)
Thread.Sleep(100)
Dim ss As Screenshot = CType(driver, ITakesScreenshot).GetScreenshot()
ss就是个图像了,想怎么剪裁啥的那不归本文管了。
PS:别想太多,现在就是整个页面——无论它高度是否超过屏幕高度。但,这只能在options.AddArguments("--headless=new")或没有=new的模式下使用,一旦你显示chrome窗口,那么它将无法突破windows对窗口高度的限制——即使你设置的足够高,也会被自动设置为不超过屏幕高度。(似乎用WINAPI设置可以突破,但如果你用鼠标移动这个窗口它又被限制,可能WIN7下如此表现,其他版本emmmmmm,记不清楚了,有兴趣的可以试一试。)
三、自动填写表单
这个有自动提交功能,而且很有趣。代码接上文:
driver.Navigate().GoToUrl("https://ooxx.com")
Thread.Sleep(2000)
driver.FindElement(By.Id("handleOrEmail")).SendKeys("aooooooooooo@163.com")
driver.FindElement(By.Id("password")).SendKeys("emmmmmmmmmmmm")
driver.FindElement(By.Id("enterForm")).Submit()
Thread.Sleep(2000)
大概这样就可以登录了。这个工具里面输入啥的都是用SendKeys,并且我没有发现直接改属性的函数——当然,这不影响你自己写一段java程序然后使用它的接口运行。很有可能还需要取一些ooxx_token啥的,打开下个网页需要用到,但这也不归本文管啊!
下面演示一段好玩的东西——因为我没整明白HTML.Select这个玩意在chromedriver里面到底咋操作,有会的还请不吝赐教:
'戳一下下拉列表,有的下拉列表现生成的,不戳不行
Dim slt = driver.FindElement(By.Name("programTypeId"))
slt.Click()
Thread.Sleep(2000)
'这个列表的text属性会列出全部option
Dim cnt As Integer = slt.Text.Split(vbCrLf).Length
'开始整活,要的选项的value=50,开始按上下吧,
For i As Integer = 1 To cnt
If slt.GetAttribute("value") = "50" Then Exit For
slt.SendKeys(Keys.ArrowDown)
Thread.Sleep(200)
Next
For i As Integer = 1 To cnt
If slt.GetAttribute("value") = "50" Then Exit For
slt.SendKeys(Keys.ArrowUp)
Thread.Sleep(200)
Next
幸亏人家网站自动记录上次选的是哪个,不然这看起来老low了——全自动填表的半自动人工智障。