gpt4 book ai didi

c# - .NET WebBrowser - FireBug 样式检查 HTML 元素

转载 作者:技术小花猫 更新时间:2023-10-29 12:27:48 26 4
gpt4 key购买 nike

是否可以使用 .NET 3.5/4.0 在 WinForm Web 浏览器中检查 HTML 元素?

可能使用 IHighlightRenderingServices 接口(interface)或 Html Agility Pack?

我希望应用程序像 FireBug 一样运行:

只需将鼠标悬停在要检查的元素上,然后单击它。在 1.7 之前的 Firebug 版本中,这会自动切换到 HTML 面板并在节点 View 中选择适当的元素。

Inspect Element

编辑:

哇,我刚看到http://www.selectorgadget.com/这正是我想要做的。它是用 Javascript 编写的,在查看了过去 2 小时的源代码后,我仍然不知道如何将它合并到我的程序中......

据我所知,它使用 DOM 元素的标记化和递归分析来找出 CSS 选择器路径:http://www.selectorgadget.com/stable/lib/dom.js .

编辑:好的!我已将 selectorgadget 加载到我的应用程序中。它允许您选择与 Firebug 完全相同的 HTML 元素!甚至创建 Xpath 查询。

enter image description here

但是,我使用的是 AxWebBrowser,我一直在思考如何让它与 HtmlAgilityPack 一起工作......

    private void xpathQuery_Click(object sender, EventArgs e)
{
// Load Browser
HtmlWindow window = axWebBrowser1.Document.Window; // <---- 'object' does not contain a definition for 'Window'

string str = window.Document.Body.OuterHtml;

// Load HTML
HtmlAgilityPack.HtmlDocument HtmlDoc = new HtmlAgilityPack.HtmlDocument();
HtmlDoc.LoadHtml(str);

//Process Xpath Query
HtmlAgilityPack.HtmlNodeCollection Nodes = HtmlDoc.DocumentNode.SelectNodes(xpathText.Text);

//Print in Text box
foreach (HtmlAgilityPack.HtmlNode Node in Nodes)
{
richTextBox1.Text += Node.OuterHtml + "\r\n";
}
}

编辑:我无法让 AxWebBrowser 与 HtmlAgilityPack 一起工作,所以我只是使用 WebClient 类加载 URL,然后使用 HtmlAgilityPack 解析它。

我即将完成 Web Scraper。它的功能类似于 Visual Web Ripper 和所有其他价格超过 1,000 美元的产品。

enter image description here

最佳答案

我以前确实做过。您必须将文档转换为 IExpando,然后您可以对其进行反射调用以获取成员。我实际上创建了一个 DynamicNode 类,它允许您使用 dynamic 关键字与文档进行交互。

您可能想改用 mshtml COM 对象:Reusing MSHTML

  1. 在 COM 引用列表中添加对 mshtml 的引用
  2. 创建 var document = new mshtml.HTMLDocument();
  3. 的实例
  4. 转换到 IExpando:var window = (IExpando)document.parentWindow;
  5. 创建动态对象包装器(见下文)
  6. 使用动态关键字与文档进行交互。

例如这是我的动态节点:

class DynamicNode : DynamicObject, IExpando, IEnumerable
{
private IExpando value;

public DynamicNode(IExpando value)
{
this.value = value;
}

public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result)
{
switch (binder.Operation)
{
case System.Linq.Expressions.ExpressionType.Convert:
case System.Linq.Expressions.ExpressionType.ConvertChecked:
result = this.value;
return true;
}

return base.TryUnaryOperation(binder, out result);
}

public override IEnumerable<string> GetDynamicMemberNames()
{
return this.value
.GetMembers(BindingFlags.Instance | BindingFlags.Public)
.Select(m => m.Name)
.Distinct()
.ToArray();
}

public override bool TryConvert(ConvertBinder binder, out object result)
{
result = this.value;
return true;
}

public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
if (indexes.Length == 1)
{
var memberName = indexes[0].ToString();
result = ReflectionHelpers.GetValue(this.value, memberName);
result = DynamicNode.Wrap(result);
return true;
}

return base.TryGetIndex(binder, indexes, out result);
}

public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
{
if (indexes.Length == 1)
{
var memberName = indexes[0].ToString();
value = DynamicNode.Unwrap(value);
ReflectionHelpers.SetValue(this.value, memberName, value);
return true;
}

return base.TrySetIndex(binder, indexes, value);
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (base.TryGetMember(binder, out result))
return true;

result = ReflectionHelpers.GetValue(this.value, binder.Name);
result = DynamicNode.Wrap(result);
return true;
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
ReflectionHelpers.SetValue(this.value, binder.Name, value);
return true;
}

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
if (binder.Name == "New")
{
var constructorArgs = new object[args.Length - 1];
Array.ConstrainedCopy(args, 1, constructorArgs, 0, constructorArgs.Length);

result = ReflectionHelpers.New(this.value, (string)args[0], constructorArgs);
}
else
{
result = ReflectionHelpers.Invoke(this.value, binder.Name, args);
}

result = DynamicNode.Wrap(result);
return true;
}

public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
IExpando self = this.value;
object[] constructorArgs = new object[0];

if (args.Length > 0)
{
self = (IExpando)DynamicNode.Unwrap(args[0]);
constructorArgs = new object[args.Length - 1];
Array.ConstrainedCopy(args, 1, constructorArgs, 0, constructorArgs.Length);
}

result = ReflectionHelpers.Call(this.value, self, constructorArgs);
result = DynamicNode.Wrap(result);
return true;
}

private static object Wrap(object value)
{
if (value != null && Marshal.IsComObject(value))
value = new DynamicNode((IExpando)value);

return value;
}

public static object Unwrap(object value)
{
DynamicNode node = value as DynamicNode;
if (node != null)
return node.value;

return value;
}

public IEnumerator GetEnumerator()
{
var members = this.value.GetProperties(BindingFlags.Public | BindingFlags.Instance);

var indexProperties = new List<Tuple<int, PropertyInfo>>();
var isArray = true;
foreach (var member in members)
{
int value = 0;
if (!int.TryParse(member.Name, out value))
{
isArray = false;
break;
}

var propertyMember = member as PropertyInfo;
if (propertyMember != null)
indexProperties.Add(Tuple.Create(value, propertyMember));
}

if (isArray)
{
indexProperties.Sort((left, right) => left.Item1.CompareTo(right.Item1));
foreach (var prop in indexProperties)
yield return prop.Item2.GetValue(this.value, null);
}
else
{
foreach (var member in members)
yield return member.Name;
}
}

#region IExpando
FieldInfo IExpando.AddField(string name)
{
return this.value.AddField(name);
}

MethodInfo IExpando.AddMethod(string name, Delegate method)
{
return this.value.AddMethod(name, method);
}

PropertyInfo IExpando.AddProperty(string name)
{
return this.value.AddProperty(name);
}

void IExpando.RemoveMember(MemberInfo m)
{
this.value.RemoveMember(m);
}

FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
{
return this.value.GetField(name, bindingAttr);
}

FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
{
return this.value.GetFields(bindingAttr);
}

MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
{
return this.value.GetMember(name, bindingAttr);
}

MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
{
return this.value.GetMembers(bindingAttr);
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
{
return this.value.GetMethod(name, bindingAttr);
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
{
return this.value.GetMethod(name, bindingAttr, binder, types, modifiers);
}

MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
{
return this.value.GetMethods(bindingAttr);
}

PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
{
return this.value.GetProperties(bindingAttr);
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
return this.value.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
{
return this.value.GetProperty(name, bindingAttr);
}

object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
return this.value.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}

Type IReflect.UnderlyingSystemType
{
get { return this.value.UnderlyingSystemType; }
}
#endregion
}

[ComVisible(true)]
public class ScriptObject : IReflect, IExpando
{
private readonly Type type;
private dynamic _constructor;
private dynamic _prototype;

public ScriptObject()
{
type = this.GetType();
}

[DispId(0)]
protected virtual object Invoke(object[] args)
{
return "ClrObject";
}

public dynamic constructor
{
get { return _constructor; }
set { this._constructor = value; }
}

public dynamic prototype
{
get { return _prototype; }
set { this._prototype = value; }
}

public string toString()
{
return "ClrObject";
}

#region IReflect Members
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
{
return type.GetMethod(name, bindingAttr, binder, types, modifiers);
}

MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
{
return type.GetMethod(name, bindingAttr);
}

protected virtual MethodInfo[] GetMethods(BindingFlags bindingAttr)
{
return type.GetMethods(bindingAttr);
}

MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
{
return GetMethods(bindingAttr);
}

FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
{
return type.GetField(name, bindingAttr);
}

FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
{
return new FieldInfo[0]; // type.GetFields(bindingAttr);
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
{
return type.GetProperty(name, bindingAttr);
}

PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
return type.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}

protected virtual PropertyInfo[] GetProperties(BindingFlags bindingAttr)
{
return type.GetProperties(bindingAttr);
}

PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
{
return GetProperties(bindingAttr);
}

MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
{
return type.GetMember(name, bindingAttr);
}

MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
{
return type.GetMembers(bindingAttr);
}

protected virtual object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
if (name == "[DISPID=0]")
{
return this.Invoke(args);
}
return type.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}

object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
return this.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}

Type IReflect.UnderlyingSystemType
{
get { return type.UnderlyingSystemType; }
}
#endregion

#region IExpando Members
public FieldInfo AddField(string name)
{
throw new NotImplementedException();
}

public MethodInfo AddMethod(string name, Delegate method)
{
throw new NotImplementedException();
}

public PropertyInfo AddProperty(string name)
{
throw new NotImplementedException();
}

public void RemoveMember(MemberInfo m)
{
throw new NotImplementedException();
}
#endregion
}

public static class ReflectionHelpers
{
private const BindingFlags DefaultFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;

public static object New(this IExpando scope, string functionName, params object[] args)
{
var constructor = (IExpando)scope.GetValue(functionName);
var proto = constructor.GetValue("prototype");

var obj = (IExpando)scope.GetValue("Object");
var instance = (IExpando)obj.Invoke("create", new object[] { proto });
Call(constructor, instance, args);

return instance;
}

public static object Call(this IExpando function, IExpando scope, params object[] args)
{
object[] callArgs = new object[args.Length + 1];
callArgs[0] = scope;
Array.Copy(args, 0, callArgs, 1, args.Length);

return Invoke(function, "call", callArgs);
}

public static void SetValue(this IExpando instance, string propertyName, object value)
{
if (instance == null)
throw new ArgumentNullException("instance");

if (string.IsNullOrEmpty(propertyName))
throw new ArgumentException("Must specify a value.", "propertyName");

Invoke(instance, propertyName, InvokeFlags.DISPATCH_PROPERTYPUT, new object[] { value });
}

public static object GetValue(this IExpando instance, string propertyName)
{
return Invoke(instance, propertyName, InvokeFlags.DISPATCH_PROPERTYGET, new object[0]);
}

public static object Invoke(this IExpando instance, string functionName, object[] args)
{
if (instance == null)
throw new ArgumentNullException("instance");

if (string.IsNullOrEmpty(functionName))
throw new ArgumentException("Must specify a value.", "functionName");

return Invoke(instance, functionName, InvokeFlags.DISPATCH_METHOD, args);

}

private static object Invoke(IExpando instance, string functionName, InvokeFlags flags, object[] args)
{
try
{
args = args.Select(arg => DynamicNode.Unwrap(arg)).ToArray();
switch (flags)
{
case InvokeFlags.DISPATCH_METHOD:
var method = instance.GetMethod(functionName, DefaultFlags);
return method.Invoke(instance, args);
case InvokeFlags.DISPATCH_PROPERTYGET:
var getProp = instance.GetProperty(functionName, DefaultFlags);
return getProp.GetValue(instance, null);
case InvokeFlags.DISPATCH_PROPERTYPUT:
case InvokeFlags.DISPATCH_PROPERTYPUTREF:
var setProp = instance.GetProperty(functionName, DefaultFlags);
if (setProp == null)
setProp = instance.AddProperty(functionName);
setProp.SetValue(instance, args[0], null);
return null;
default:
throw new NotSupportedException();
}
}
catch (COMException comex)
{
switch ((uint)comex.ErrorCode)
{
// Unexpected script error. This will be handled by the IProcess.UnhandledException event
case 0x80020101:
return null;
default:
throw;
}
}
}

private enum InvokeFlags
{
DISPATCH_METHOD = 1,
DISPATCH_PROPERTYGET = 2,
DISPATCH_PROPERTYPUT = 4,
DISPATCH_PROPERTYPUTREF = 8,
}
}

您实际上可以通过这种方式将 .net 对象粘贴到文档中,或者从 .net 中拉出对象并与它们交互。您还可以将 js 作为字符串进行评估,并让它调用 .net 函数。以下是一些使用代码片段:

获取和设置一个js对象的成员:

this.host.Window.eval(@" Foo = { }; ");

var foo = this.host.Window.Foo;
foo.B = 7.11;
Assert.Equal(7.11, foo.B);

从 C# 调用 js 函数:

this.host.eval("function add(x, y) { return x + y; }");
var z = (int)this.host.Window.add(7, 11);
Assert.Equal(7 + 11, z);

将 .net 对象插入文档并从 js 调用其成员:

this.host.Window.Custom2 = new Custom2();    
this.host.Window.eval(@"
function test() {
return Custom2.Test().Value;
}");

bool success = this.host.Window.test();
Assert.True(success);

不过,您只能将继承自 ScriptObject 的对象粘贴到文档中(在上面的代码块中定义)。好吧,我认为你可以在里面放任何东西,但如果它们不实现 IReflect,你会得到奇怪的行为。

关于c# - .NET WebBrowser - FireBug 样式检查 HTML 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9502968/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com