截取网页的最佳方式是什么? 目前我只是启动了一个 firefox 的 selenium 实例并使用 winapi 将它带到前面并制作了一个屏幕截图。 我问类似question已经。
有两点:
有什么方法可以更“程序化”地截取屏幕截图吗?
这是我现在使用的一些代码:
class FirefoxDriverEx : FirefoxDriver
{
public Process GetFirefoxProcess()
{
var fi = typeof(FirefoxBinary).GetField("process", BindingFlags.NonPublic | BindingFlags.Instance);
return fi.GetValue(this.Binary) as Process;
}
}
下面是演示截图过程的代码:
using (FirefoxDriverEx driver = new FirefoxDriverEx())
{
driver.Navigate().GoToUrl(url);
var process = driver.GetFirefoxProcess();
if (process != null)
{
var screenCapture = new ScreenCapture();
Win.SetForegroundWindow(process.MainWindowHandle.ToInt32());
}
}
现在,我正在考虑一些管理器来控制窗口队列以从中获取屏幕截图。
问题编辑。
我不是在寻找一种解决方案来获取“内存中”的屏幕截图并将其返回到 HTTP 流。因此,任何保存屏幕截图并将其保存到文件然后从那里获取它的方法都非常模糊。
问题编辑 #2。
忘记说了。需要的屏幕截图应该按照用户看到的那样制作。因此,屏幕截图应该有浏览器窗口和 Web 浏览器窗口边界内的站点。我找不到任何方法来更改在 selenium 的 WebDriver 中截取屏幕截图的模式。 WebDriver 只是在没有任何浏览器窗口的情况下对页面进行屏幕截图。
最佳答案
我推荐 getScreenshotAs。它甚至可以显示屏幕的“视线之外”部分。
这是 gr0ovy 中的一些示例代码。
import java.io.IOException
import java.net.URL
import java.nio.file.Path
import java.nio.file.Paths
import java.text.SimpleDateFormat
import org.openqa.selenium.Capabilities
import org.openqa.selenium.TakesScreenshot
import org.openqa.selenium.WebDriverException
import org.openqa.selenium.remote.CapabilityType
import org.openqa.selenium.remote.DriverCommand
import org.openqa.selenium.remote.RemoteWebDriver
import org.openqa.selenium.OutputType
import org.openqa.selenium.WebDriver
public class Selenium2Screenshot {
private WebDriver driver
private String browserType
private boolean skipScreenshots
public Selenium2Screenshot(WebDriver webDriver, String browserType, boolean skipScreenshots) {
this.driver = webDriver
this.browserType = browserType
this.skipScreenshots = skipScreenshots
}
public void takeScreenshot(String filenameBase) {
if (!skipScreenshots) {
Date today
String formattedDate
SimpleDateFormat formatter
Locale currentLocale
File scrFile
currentLocale = new Locale("en", "US")
formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", currentLocale)
today = new Date()
formattedDate = formatter.format(today)
String filename = getUiAutomationDir() + filenameBase + "_" + browserType + formattedDate + ".png"
Log.logger.info("Screenshot filename = " + filename)
try {
scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE)
JavaIO.copy(scrFile.getAbsolutePath(), filename)
} catch (Exception e) {
Log.logger.error(e.message, e)
}
} else {
Log.logger.info("Skipped Screenshot")
}
}
private String getUiAutomationDir()
{
String workingDir = System.getProperty("user.dir")
Path workingDirPath = Paths.get(workingDir)
String returnString = workingDirPath.toString() + "\\"
return returnString
}
2012 年 8 月 1 日编辑:
获取应用程序句柄代码。我确实多次复制了 stackoverflow 上的代码,但希望这与其他帖子中的代码不完全相同:-)
public static IntPtr FindWindowByPartialCaption(String partialCaption)
{
var desktop = User32.GetDesktopWindow();
var children = EnumerateWindows.GetChildWindows(desktop);
foreach (var intPtr in children)
{
var current = GetText(intPtr);
if (current.Contains(partialCaption))
return intPtr;
}
return IntPtr.Zero;
}
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowProc lpEnumFunc, IntPtr lParam);
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
public static List<IntPtr> GetChildWindows(IntPtr parent)
{
return GetChildWindows(parent, false);
}
public static List<IntPtr> GetChildWindows(IntPtr parent, bool reverse)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
if (reverse)
{
List<IntPtr> resultList = result.Reverse<IntPtr>().ToList();
return resultList;
}
else
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
}
http://www.pinvoke.net/也是一个很好的资源。
关于c# - 网页截图的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11698222/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac