- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在尝试 html agility pack,但找不到正确的方法来解决这个问题。
例如:
var findclasses = _doc.DocumentNode.Descendants("div").Where(d => d.Attributes.Contains("class"));
但是,很明显你可以添加比 div 更多的类,所以我尝试了这个..
var allLinksWithDivAndClass = _doc.DocumentNode.SelectNodes("//*[@class=\"float\"]");
但这并不能处理您添加多个类并且“ float ”只是其中一个这样的情况..
class="className float anotherclassName"
有办法处理所有这些吗?我基本上想选择所有具有类 = 并包含 float 的节点。
**答案已记录在我的博客上,完整解释位于:Html Agility Pack Get All Elements by Class
最佳答案
(更新于 2018-03-17)
正如您所发现的,问题是 String.Contains
不执行字边界检查,所以 Contains("float")
将返回 true
对于“foo float bar”(正确)和“unfloating”(不正确)。
解决方案是确保“float”(或任何您想要的类名)出现在两端的单词边界旁边。单词边界是字符串(或行)的开始(或结束)、空格、某些标点符号等。在大多数正则表达式中,这是 \b
.所以你想要的正则表达式很简单:\bfloat\b
.
使用 Regex
的缺点例如,如果您不使用 .Compiled
,它们的运行速度可能会很慢选项 - 它们的编译速度可能很慢。所以你应该缓存正则表达式实例。如果您要查找的类名在运行时发生变化,这将更加困难。
或者,您可以通过将正则表达式实现为 C# 字符串处理函数来在不使用正则表达式的情况下按单词边界搜索字符串,注意不要导致任何新字符串或其他对象分配(例如,不使用 String.Split
).
假设您只想查找具有单个设计时指定类名的元素:
class Program {
private static readonly Regex _classNameRegex = new Regex( @"\bfloat\b", RegexOptions.Compiled );
private static IEnumerable<HtmlNode> GetFloatElements(HtmlDocument doc) {
return doc
.Descendants()
.Where( n => n.NodeType == NodeType.Element )
.Where( e => e.Name == "div" && _classNameRegex.IsMatch( e.GetAttributeValue("class", "") ) );
}
}
如果您需要在运行时选择单个类名,那么您可以构建一个正则表达式:
private static IEnumerable<HtmlNode> GetElementsWithClass(HtmlDocument doc, String className) {
Regex regex = new Regex( "\\b" + Regex.Escape( className ) + "\\b", RegexOptions.Compiled );
return doc
.Descendants()
.Where( n => n.NodeType == NodeType.Element )
.Where( e => e.Name == "div" && regex.IsMatch( e.GetAttributeValue("class", "") ) );
}
如果你有多个类名并且你想匹配所有的类名,你可以创建一个 Regex
的数组对象并确保它们都匹配,或将它们组合成一个 Regex
使用环顾四周,但结果是 in horrendously complicated expressions - 所以使用 Regex[]
可能更好:
using System.Linq;
private static IEnumerable<HtmlNode> GetElementsWithClass(HtmlDocument doc, String[] classNames) {
Regex[] exprs = new Regex[ classNames.Length ];
for( Int32 i = 0; i < exprs.Length; i++ ) {
exprs[i] = new Regex( "\\b" + Regex.Escape( classNames[i] ) + "\\b", RegexOptions.Compiled );
}
return doc
.Descendants()
.Where( n => n.NodeType == NodeType.Element )
.Where( e =>
e.Name == "div" &&
exprs.All( r =>
r.IsMatch( e.GetAttributeValue("class", "") )
)
);
}
使用自定义 C# 方法而不是正则表达式进行字符串匹配的优势是假设性能更快并减少内存使用(尽管 Regex
在某些情况下可能更快 - 总是首先分析您的代码, children !)
下面这个方法:CheapClassListContains
提供了一个快速的字边界检查字符串匹配函数,可以像regex.IsMatch
一样使用。 :
private static IEnumerable<HtmlNode> GetElementsWithClass(HtmlDocument doc, String className) {
return doc
.Descendants()
.Where( n => n.NodeType == NodeType.Element )
.Where( e =>
e.Name == "div" &&
CheapClassListContains(
e.GetAttributeValue("class", ""),
className,
StringComparison.Ordinal
)
);
}
/// <summary>Performs optionally-whitespace-padded string search without new string allocations.</summary>
/// <remarks>A regex might also work, but constructing a new regex every time this method is called would be expensive.</remarks>
private static Boolean CheapClassListContains(String haystack, String needle, StringComparison comparison)
{
if( String.Equals( haystack, needle, comparison ) ) return true;
Int32 idx = 0;
while( idx + needle.Length <= haystack.Length )
{
idx = haystack.IndexOf( needle, idx, comparison );
if( idx == -1 ) return false;
Int32 end = idx + needle.Length;
// Needle must be enclosed in whitespace or be at the start/end of string
Boolean validStart = idx == 0 || Char.IsWhiteSpace( haystack[idx - 1] );
Boolean validEnd = end == haystack.Length || Char.IsWhiteSpace( haystack[end] );
if( validStart && validEnd ) return true;
idx++;
}
return false;
}
HtmlAgilityPack 有点停滞不支持.querySelector
和 .querySelectorAll
,但是有第三方库用它扩展 HtmlAgilityPack:即 Fizzler和 CssSelectors . Fizzler 和 CssSelectors 都实现了 QuerySelectorAll
, 所以你可以像这样使用它:
private static IEnumerable<HtmlNode> GetDivElementsWithFloatClass(HtmlDocument doc) {
return doc.QuerySelectorAll( "div.float" );
}
使用运行时定义的类:
private static IEnumerable<HtmlNode> GetDivElementsWithClasses(HtmlDocument doc, IEnumerable<String> classNames) {
String selector = "div." + String.Join( ".", classNames );
return doc.QuerySelectorAll( selector );
}
关于c# - Html Agility Pack 按类获取所有元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13771083/
我在运行 git gc --prune=now 并得到结果 Counting objects: 100% (619263/619263), done. Delta compression using
我想获取某个类中的所有链接。 HTML 的一个例子是 ES M3 E-mini S&P500 June 2013
我正在 32 位 ARM mcu(Atmel SAM4SD32C,Cortex-M4/ARMv7E-M 部件)上实现二进制日志记录系统,并且正在设计我的数据结构。我的目标是将日志格式描述为一个压缩结构
以下测试代码: [Test] public void PossibleHtmlAgilityPackBug() { const string html = @""; var doc =
如何利用 D3 圆包布局来得到类似这样的图表: (即使有更细长的椭圆)? 这种图表样式的关键应用是更容易放置标签。 这是 jsfiddle这演示了我为其他目的制作的圆包,但我想对于任何想要试验和测试涉
在 C 语言中,编译器将按照声明的顺序排列结构成员,并在成员之间或最后一个成员之后插入可能的填充字节,以确保每个成员都正确对齐。 gcc 提供了一个语言扩展,__attribute__((packed
在 C 语言中,编译器将按照声明的顺序排列结构成员,并在成员之间或最后一个成员之后插入可能的填充字节,以确保每个成员都正确对齐。 gcc 提供了一个语言扩展,__attribute__((packed
在我正在处理的 WPF 应用程序中尝试使用合并的 ResourceDictionaries 解决问题时,我遇到了这个奇怪的问题。 我在外部 DLL(“通用”)中定义了自定义控件(TextButton、
在使用 webpack、webpacker gem 和 Rails 5.1 时,我注意到第一次运行 rspec 会生成 public/packs 和 public/packs-test 。 这些目录是
给定一个 HTML 文档,我想识别文档中的所有数字并在数字周围添加自定义标签。现在,我使用以下内容: HtmlNodeCollection bodyNode = htmlDoc.DocumentNod
我正在尝试使用 #pragma pack (n) 对齐数据成员.以下面为例: #include using namespace std; #pragma pack(8) // or (16) str
我正在尝试让 Html Agility Pack 在我的情况下工作。我需要检测现有 HTML 页面中的所有脚本元素并删除它们,将更改保存到另一个文件。在这里,bodyNode 返回正确数量的脚本标签,
我正在使用 GitLab,需要创建一个 .gitlab-ci.yml 脚本来为生成 nuGet 包的项目运行持续集成管道。 我在寻找可靠的文档来回答这个问题时遇到严重问题: 我应该使用 dotnet
我一直在尝试查找这个问题,但没有找到有效的解决方案。我的编译器忽略了#pragma pack(push) #pragma pack(2) 和 __ attribute __ ((aligned (2)
我正在尝试在 Ubuntu 10.10 上使用 Solaris Studio for Linux。 当我尝试构建以下代码时, const char * 名称 [] = { "苹果", "橙子", "芒
我正在尝试从 HTML 中删除不必要的内容。具体来说,我想删除评论。我找到了一个很好的解决方案( Grabbing meta-tags and comments using HTML Agility
我正在VHDL中的一个项目上工作,我需要从开关中获取4位输入,并根据其他开关的值向右或向左移动一定数量的位,该按钮需要在向右/向左移位之间切换。但是,当我尝试在Xilinx ISE中实现代码时,出现以
我有一台具有 SSH 访问权限的服务器,我想在那里放置一个 Git 源代码库。我刚刚在本地创建了一个 --bare --shared 存储库并将其复制到每个 SCP 的服务器。现在我想根据 SSH u
-moz-box-pack(或 box-pack)的 justify 属性似乎在 Firefox 中被忽略了。 Live example从我们的网站。每行中的数字应该右对齐,它们在 Chrome 中也
这是我的代码。我想知道如何“正确地”读取 BMP 文件,然后在不强制打包结构的情况下读取 header 值。 typedef struct __attribute__((packed)){ uint8
我是一名优秀的程序员,十分优秀!