컀μ€ν
ν¬λ‘€λ¬
λ ν¬λ‘€λ§ λ° μ 보 κ°κ³΅ κ³Όμ μ μλννκ±°λ, νλ‘κ·Έλλ¨Έκ° μ’ λ μ½κ²
ν¬λ‘€λ¬λ₯Ό μμ±ν μ μλλ‘ λμμ€ μ μλ νλ‘κ·Έλ¨μ
λλ€.
μ΄ λ΄μ©μ 컀μ€ν ν¬λ‘€λ¬μ 컨μ μ΄λ©°, μ€κ³ μ€ μΈμ λ μ§ λ°λ μ μμ΅λλ€.
HTML
μ μΉ λΈλΌμ°μ Έμ μμ²μΌλ‘ μλ²μμ λ€μ΄λ‘λλλ νμΌμ
λλ€.
μ΄ νμΌμλ .js
μ κ°μ λ©ννμΌ μ λ³΄κ° ν¬ν¨λλ©°, μΉ λΈλΌμ°μ Έλ λ©ννμΌμ
λͺ¨λ λΉλκΈ°λ‘ λ€μ΄λ‘λνμ¬ μλ°μ€ν¬λ¦½νΈ μμ§μΌλ‘, λλ κΈ°ν μΉ λΈλΌμ°μ μμ μ 곡νλ κΈ°λ₯λ€λ‘ μ€νν©λλ€.
μΉ λΈλΌμ°μ Έλ μΉ νμ΄μ§λ₯Ό λ‘λ©ν λ ν¬κ² λ€μκ³Ό κ°μ κ³Όμ μ κ±°μΉλ€κ³ ν μ μμ΅λλ€.
HTML λ€μ΄λ‘λ
-> HTML λΆμ
-> META(.js, .css λ±λ±) λ°μ΄ν° μμ²
-> λ λλ§ μμ λ° Javascript, WASM, PHP λ± μ½λ μ€ν
HTML λΆμ
λ¨κ³μμ μΉ λΈλΌμ°μ Έλ HTMLμ νμ±νκ³ κ΅μ νλ κ³Όμ μ κ±°μΉ©λλ€.
κ΅μ κ³Όμ μ HTML νμΌμ΄ HTML λ¬Έλ²μ λ§μ§ μλ κ²½μ° μ΄λ₯Ό μλμΌλ‘ μμ ν΄μ£Όλ κ³Όμ μ
λλ€.
μλ₯Ό λ€μ΄ <table>
νκ·Έ νμμ <tbody>
κ° μ€μ§μκ³ λ°λ‘ <tr>
νκ·Έκ° λμ¨λ€λ©΄ HTML λΆμλ¨κ³μμ <tbody>
νκ·Έλ₯Ό μΆκ°ν¨μΌλ‘μ¨ HTMLμ κ΅μ ν©λλ€.
λ°λΌμ μΉ λΈλΌμ°μ Έμ κ°λ°μλꡬμμ νμλλ HTMLμ URL
λ‘ λ€μ΄λ‘λν HTMLκ³Ό μλΉν λ€λ₯Ό μ μμ΅λλ€.
XPath
λ HTMLμ νΉμ λ
Έλλ₯Ό νλμ μμΌλ‘ λνλΈ κ²μ
λλ€.
μ΄ μμ μ¬λ¬κ°μ λ
Έλλ₯Ό κ°λ¦¬ν¬ μ μκ³ , νλμ λ
Έλλ§ κ°λ¦¬ν¬ μ μμ΅λλ€.
ν¬λ‘€λ¬λ₯Ό λ§λ€ λ μ£Όλ‘ XPath
μ λͺ¨λ μ€νλ€μ λ루 νμ©νμ§λ§,
HTMLμ λΆμν΄μ£Όλ λΌμ΄λΈλ¬λ¦¬λ€ λλΆμ΄ κ΅³μ΄ λͺ¨λ μ€νλ€μ μ¬μ©νμ§ μκ³
νΉμ νλμ λ
Έλ μμΉλ₯Ό μ μ μλ XPath
λ₯Ό μ½κ² μ»μ μ μμ΅λλ€.
ν¬λ‘¬ κ°λ°μ λꡬμ Inspectorλ‘ νΉμ Elementsλ₯Ό μ ννκ³ , νΉμ HTML λ
Έλμ
λ§μ°μ€ μ€λ₯Έμͺ½ ν΄λ¦ ν Copy -> Copy full XPath
λ₯Ό λλ₯΄λ©΄ νΉμ ν λ
Έλμ μμΉλ₯Ό μ μ
μλ XPath
κ° λ³΅μ¬λ©λλ€.
/html/body/div[3]/div[1]
/html[1]/body[1]/div[3]/div[1]
μμ κ°μ μ΄λ€ μμ΄ λ³΅μ¬λλλ° μ΄ μμ΄ λ°λ‘ XPath
μ
λλ€.
λ μμ κ°μ νκΈ°μ΄λ©°, μλμμ μ£Όλ‘ μ¬μ©ν κ²λλ€.
HTMLμ νΈλ¦¬κ΅¬μ‘°μ΄λ©° νΈλ¦¬μ νμ λ
Έλλ€μ μμκ° μκΈ° λλ¬Έμ μμ κ°μ νκΈ°κ° κ°λ₯ν©λλ€.
μ μμ <html>
νκ·Έλ₯Ό κ°μ§ 첫 λ²μ§Έ νμ λ
Έλλ₯Ό μ ννκ³ , κ·Έ νμ λ
Έλμ 첫 λ²μ§Έ
<body>
λ
Έλλ₯Ό μ ννκ³ , μ΄μ μΈ λ²μ§Έλ‘ λμ€λ <div>
νκ·Έλ₯Ό μ ννκ³ , λ§μ§λ§μΌλ‘
첫 λ²μ§Έλ‘ λμ€λ <div>
λ₯Ό μ ννλΌλ μλ―Έ μ
λλ€.
μΈ λ²μ§Έλ‘ λμ€λ <div>
νκ·Έλ <body>
μ λͺ¨λ νμ λ
Έλλ€ μ€μ div
νκ·Έλ₯Ό κ°μ§λ
λͺ¨λ νκ·Έλ€μ μμλλ‘ λμ΄νμ λ μΈ λ²μ§Έ λμ€λ div
λ₯Ό μ ννλΌλ μλ―Έμ
λλ€.
ν¬λ‘€λ§μλ ν¬κ² λ κ°μ§ λ°©λ²μ΄ μμ΅λλ€.
μ μ λΆμκ³Ό λμ λΆμμ
λλ€.
μ μ λΆμμ URL
μ ν΅ν΄ λ°λ‘ λ€μ΄λ‘λλ°μ HTMLνμΌμ λ°λ‘ λΆμνλ λ°©λ²μ΄λ©°,
λμ λΆμμ μΉ λΈλΌμ°μ Έκ° λ©νλ°μ΄ν° λ° μλ°μ€ν¬λ¦½νΈ μ½λ λ±μ μν΄ λΉλκΈ°μ μΌλ‘ μΆκ°λλ μΉ μμλ€μ λΆμνλ λ°©λ²μ
λλ€.
μ μ λΆμμ BeautifulSoup4
λ HtmlAgilityPack
κ³Ό κ°μ HTML νμ± λꡬλ₯Ό μ¬μ©νλ©΄ μ½κ² ꡬνν μ μμ΅λλ€.
HTMLμ κΈ°λ³Έμ μΌλ‘ #document
λ
Έλλ₯Ό 루νΈλ
Έλλ‘νλ νΈλ¦¬κ΅¬μ‘°μ΄λ©°, λ°λΌμ νΈλ¦¬ μλ£κ΅¬μ‘°λ‘ μ½κ² λνλΌ μ μμ΅λλ€.
λμΆ© μ΄λ κ²
μ μ λΆμμμ HTMLμ΄ νΈλ¦¬ κ΅¬μ‘°μΈ κ²μ μ κ·Ήμ μΌλ‘ νμ©ν©λλ€.
<table>
νκ·Έμ νμ λ
Έλλ€μ <tr>
λ€λ‘ ꡬμ±λμ΄μμΌλ©°, <tr>
λ€μ μ νμΌλ‘ λνλ©λλ€.
μλ₯Όλ€μ΄ λ€μκ³Ό κ°μ κ²μνμ λΆμν΄λ΄ μλ€.
μ¬μ§μ μ°μΈ‘μμ λ³Ό μ μλ€μνΌ <table>
λ
Έλλ <caption>
, <tbody>
λ±μ νμλ
Έλλ₯Ό κ°μ§λ©°
<tbody>
λ <tr>
λ€μ λ
Έλλ‘ κ°μ§λλ€.
μ¬κΈ°μ <tr>
νκ·Έλ€μ΄ μ νμ μΌλ‘ λνλ¨μ μ μ μμ΅λλ€.
κ·Έλ¬λ©΄ XPath
λ‘ λ€μκ³Ό κ°μ΄ λνλΌ μ μμ΅λλ€.
.../table[1]/tbody[1]/tr[1]
.../table[1]/tbody[1]/tr[2]
.../table[1]/tbody[1]/tr[3]
...
μ¬κΈ°μ .../table[1]/tbody[1]
λΆλΆμ λͺ¨λ νμ λ
Έλμμ 곡ν΅μ μΌλ‘ λνλλ λΆλΆμ
λλ€.
μ΄ λΆλΆλ€μ μ κ±°νλ©΄ <tr>
λ
Έλλ€μ΄ μ νμ μΌλ‘ λμ΄λμ΄μλ λΆλΆμ΄ 보μ
λλ€.
μ΄μ λͺ¨λ <tr>
λ
Έλλ€μ λ°©λ¬ΈνκΈ° μν΄ λ€μκ³Ό κ°μ λ°λ³΅λ¬Έμ μμ±ν μ μμ΅λλ€.
HtmlTree tree = HtmlTree.Parse(html)
string parent = '../table[1]/tbody[1]'
for ( int i = 0; ; i++ )
{
string child_xpath = parent + '/tr[' + (i+1) + ']'
Node child_node = tree.select_xpath(child)
if (child_node == nullptr) break;
// ...
}
κ°λ¨νκ² μ νλλ‘λ νμν μ μμ΅λλ€.
.../table[1]/tbody[1]/tr[{i+1}]
μ μ½λλ₯Ό μ΄μ©ν΄ μμ λ Έλλ₯Ό μ½κ² λ°©λ¬Έν μ μκ³ , λͺ¨λ μμ λ Έλλ€μ΄ κ°μ νμμ κ°μ§λ€λ©΄ νλμ 루ν΄μΌλ‘ λͺ¨λ μμμ μ½κ² λΆμν μ μμ΅λλ€.
μ€μ λ‘ μ νμ΄μ§(λμ νκ°€ κ²μν λͺ©λ‘)μ C#
μΌλ‘ ꡬνν μ½λλ λ€μκ³Ό κ°μ΅λλ€.
public class Pattern
{
public string Number;
public string Icon;
public string Title;
public string Author;
public string WriteTime;
public string Views;
public string UpVote;
}
public Pattern Extract(string html)
{
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
var result = new Pattern();
var root_node = document.DocumentNode;
for (int i = 1; ; i++)
{
var node = root_node.SelectSingleNode($"/html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[{3+i*1}]");
if (node == null) break;
result.Number = node.SelectSingleNode("./td[1]").InnerText;
result.Icon = node.SelectSingleNode("./td[2]/a[1]/em[1]").InnerText;
result.Title = node.SelectSingleNode("./td[2]/a[1]").InnerText;
result.Author = node.SelectSingleNode("./td[3]").InnerText;
result.WriteTime = node.SelectSingleNode("./td[4]").InnerText;
result.Views = node.SelectSingleNode("./td[5]").InnerText;
result.UpVote = node.SelectSingleNode("./td[6]").InnerText;
}
}
μ΄λ κ² λ Έλλ€μ κ³΅ν΅ λΆλΆ (μ΅μ κ³΅ν΅ μ‘°μ - LCA)μ μ°Ύλ λ°©λ²μ μμΌλ‘ ν¬λ‘€λ§ λ°μλνμ ν¬ν¨ν λͺ¨λ λΆλΆμμ μ£Όλ‘ μ¬μ©λ©λλ€. μ μ½λλ λ°μλν κΈ°λ₯μΌλ‘ μλμΌλ‘ ꡬνλ μ½λμ λλ€.
ν΄λ¬μ€ν°λ§μ λΉμ·ν λΆλΆλ€μ λ¬Άλ κ²μ μλ―Έν©λλ€. μΉ νμ΄μ§μμ λΉμ·ν λΆλΆλ€μ λ¬Άλ κ²μ μλ‘ λ€μ΄λ΄ μλ€.
μμ κ°μ΄ λΉμ·ν λΆλΆλ€μ μλμΌλ‘ μ°Ύμλ΄κ³ μ 보λ€μ μΆμΆνλ κ²μ μ£Ό λͺ©μ μΌλ‘, μ¬λ¬ ν΄λ¬μ€ν°λ§ λ°©λ²λ€ λ§λ€μ΄ μλνμ΅λλ€.
μ ν ν΄λ¬μ€ν
μ μ νμΌλ‘ λμ΄λ μμλ€μ ν΄λ¬μ€ν°λ§νλ λ°©λ²μ
λλ€.
2.3
μ μ¬μ§μ 보면 κ²μλ¬Ό λͺ©λ‘, μ΄λ μ΅κ·Ό λ°©λ¬Έ κ°€λ¬λλ€,
ν₯ν κΈ μμ, κ°€λ¬λ¦¬ 리μ€νΈλ€μ΄ μμλλ‘ λμ΄λμ΄μλ κ±Έ λ³Ό μ μμ΅λλ€.
μ΄λ° 리μ€νΈλ€μ΄ μ ν ν΄λ¬μ€ν°λ§μ λμμ΄ λ©λλ€.
μ΄ λ°©λ²μ ν΅ν΄ λλΆλΆμ μΉ μμλ€μ λΆμν μ μλ€κ³ κΈ°λν©λλ€.
μ ν ν΄λ¬μ€ν°λ§μ κΈ°λ³Έμ μΈ μμ΄λμ΄λ μ΄λ€ νΉμ λ Έλμ νμλ Έλλ€μ μ μ¬λλ₯Ό λΉκ΅νλ κ²μ λλ€. νμ λ Έλλ€μ΄ λ§κ³ μ νλκ° λλ€λ©΄ μ νμΌλ‘ λμ΄λ λΆλΆμ΄ κ²μλμμ νλ₯ μ΄ λ§€μ° λμ΅λλ€. λ€μ μμ λ μ ν ν΄λ¬μ€ν°λ§μ ν΅ν΄ μ νμ μμλ₯Ό μ°Ύμ κ²°κ³Όμ λλ€.
μ μ¬μ§μμ μ’μΈ‘μ μ ν ν΄λ¬μ€νΈλ§μ κ²°κ³Όμ΄κ³ , μ°μΈ‘μ κ°μ₯ λ§μ μμλ€κ³Ό μ νλκ° λμ
κ²°κ³Όλ₯Ό νλ μ νν κ²°κ³Όλ₯Ό κ΅΅μ λ
Έλμ λ°μ€λ‘ λνλΈ κ²°κ³Όμ
λλ€.
Accuracy
κ° 1λ‘ λͺ¨λ νμλ
Έλλ€μ΄ κ°μ ννλ₯Ό κ°μ§κ³ μμΌλ©°, μ΄λ° νμλ
Έλλ€μ΄ 51κ°λμλ
λͺ¨μ΅μ λ³Ό μ μμ΅λλ€.
λ€μμ μ΄ κΈ°λ₯μ ꡬνν μ½λμ λλ€.
public List<(int, double, HtmlNode, List<HtmlNode>)> LinearClustering(int min_child_count = 2, double min_diff_rate = 0.6)
{
var result = new List<(int, double, HtmlNode, List<HtmlNode>)>();
// λͺ¨λ λ
Έλλ€ μν
// foreach μ΄μ€λ£¨νλ λͺ¨λ λ
Έλλ₯Ό μνν¨.
foreach (var nn in depth_map)
foreach (var node in nn)
{
if (node.ChildNodes.Count >= min_child_count)
{
var ff = filtering_child_node(node);
var h2 = get_child_node_hashs_2nd(ff);
if (h2.Count == 0)
continue;
var diff = estimate_diff_node_hashs(h2);
if (diff >= min_diff_rate)
result.Add((ff.Count, diff, node, ff));
}
}
return result;
}
private string get_child_node_hash(HtmlNode node)
{
return node.Name + "/" + string.Join("/", node.ChildNodes.Select(x => x.Name));
}
// μΈλͺ¨μλ νμ λ
Έλλ€μ μμ ν¨
private List<HtmlNode> filtering_child_node(HtmlNode node)
{
var childs = node.ChildNodes.ToList();
// μ£Όμμ΄λ μ€ν¬λ¦½νΈ ν
μ€νΈκ°μ΄ HTML ꡬ쑰μ ν° κ΅¬μ‘°μ
// ν° μν₯μ λ―ΈμΉλ λ
Έλκ° μλλ©΄ λͺ¨λ λΉκ΅ λμμμ μμ ν¨
childs.RemoveAll(x => x.Name == "#comment";
childs.RemoveAll(x => x.Name == "script");
childs.RemoveAll(x => x.Name == "#text");
childs.RemoveAll(x => x.Name == "meta");
childs.RemoveAll(x => x.Name == "link");
childs.RemoveAll(x => x.Name == "title");
childs.RemoveAll(x => x.Name == "head");
childs.RemoveAll(x => x.Name == "style");
if (node.Name == "tbody" || node.Name == "table")
return childs.Where(x => x.Name == "tr").ToList();
return childs;
}
private List<string> get_child_node_hashs_2nd(List<HtmlNode> child_nodes)
{
return child_nodes.Select(x => get_child_node_hash(x)).ToList();
}
// hashsμ μμ μ€ κ°μ₯ λ§μ κ³΅ν΅ λ
Έλλ€μ κ°μλ₯Ό hashsμ μμ κ°μλ‘ λλκ°
private double estimate_diff_node_hashs(List<string> hashs)
{
var hash = new Dictionary<string, int>();
hashs.ForEach(x =>
{
if (!hash.ContainsKey(x))
hash.Add(x, 0);
hash[x] += 1;
});
return hash.Select(x => x.Value).Max() / (double)hashs.Count;
}
μΉ λμμ΄λ(νλ‘ νΈμλ κ°λ°μ)λ μ΄μ©μλ€μ μν UI/UXλ₯Ό μ€κ³λ₯Ό νμ κ°λ₯μ±μ΄ λ§€μ° λμ΅λλ€. μ κ·ΌνκΈ° μ¬μ΄ λΆλΆ(맨 μ²μμ 보μ΄λ λΆλΆ)μ κ°μ₯ μ€μν μ 보μ μμΌλ‘ μ€λͺ ν λ΄μ©λ€μ μμ½ν΄ νμλμ΄μμ νλ₯ μ΄ λ§€μ° λμΌλ©° νμ΄μ§ νλ¨μλ μΉ νμ΄μ§μ μλλ₯Ό μ ννκ² μ λ¬νκΈ° μν μ 보λ€μ μ 곡νμ κ°λ₯μ±μ΄ λμ΅λλ€. μΉ νμ΄μ§μμ κ°μ₯ λ§μ λΆλΆμ μ°¨μ§νλ λΆλΆμ΄ κ°μ₯ ν΅μ¬μ΄ λλ λΆλΆμ΄λ©°, λ°λΌμ μ΄ λΆλΆμ΄ κ°μ₯ μ€μν λΆλΆμΌ κ°λ₯μ±μ΄ μ μΌ λμ΅λλ€.
μ€νμΌ μ 보λ₯Ό μ»μ΄μ€λ κ²μ μΉ λΈλΌμ°μ Έμ λμμ΄ νμν©λλ€. μΉ λΈλΌμ°μ Έμμ μ΄λ€ μμκ° μ΄λ μ λμ ν¬κΈ°λ₯Ό κ°μ§λ μ§μ λν μ 보λ₯Ό λͺ¨λ κ°μ Έμ€κ³ , μ΄μ μ΄λ€ λ Έλκ° μ°¨μ§νλ μμμ λμ΄λ₯Ό, κ·Έ λ Έλμ νμ λ Έλλ€μ΄ μ°¨μ§νλ μμμ λμ΄λ₯Ό ν©μΉ κ°μΌλ‘ λλ κ°μ μμλ₯Ό ꡬνμ¬ μ΄λ€ μμμ μ μ©λ©΄μ μ ꡬν©λλ€.
μ μ©λ©΄μ μ΄ μμ λ Έλμ λμ΄μ λΉμ·νλ©΄μ νμ΄μ§μμ μ°¨μ§νλ λμ΄κ° κ°μ₯ λκ±°λ, νμ λ Έλμ κ°μκ° λ§μ μλ‘ μ¬μ©μμκ² μ€μνλ€κ³ μΈμλ κ°λ₯μ±μ΄ λμ΅λλ€.
ν¨ν΄ λΆμ λ°©λ²μ μ΄λ€ λ Έλμ κ·Έ νμ λ Έλλ€μ΄ λͺ¨λ ν¬ν¨λ μνμ κ΅¬μ‘°κ° νμ΄μ§μ λ€λ₯Έ κ³³μμ λνλλμ§, λν μ΄λμ λμ μ μ¬λλ₯Ό κ°μ§λ©΄μ λνλλμ§λ₯Ό λΆμνλ λ°©λ²μ λλ€. ν¨ν΄ λΆμμ ν΅ν΄ μμ νκΉ μμ°μ±μ κ·Ήλνμν¬ μ μμ΅λλ€.
HTML λ
Έλλ₯Ό μ νν μν€κΈ° μν λ°©λ²μΌλ‘ μ¬λ¬λ°©λ²μ΄ μκ² μ§λ§,
μ΄λ² ν¨ν΄ λΆμ λ°©λ²μμ νμνμμ μ΄μ©ν΄ μ μΌν ν¨ν΄ λ¬Έμμ΄μ μμ±ν©λλ€.
make_string
ν¨μλ νΉμ λ
Έλλ₯Ό μ ννν©λλ€.
// for DP
Dictionary<HtmlNode, string> msdp = new Dictionary<HtmlNode, string>();
private string make_string(HtmlNode node)
{
if (node.ChildNodes.Count == 0)
{
if (node.Name == "#text")
return "#";
return $"({node.Name})";
}
if (msdp.ContainsKey(node))
return msdp[node];
var ms = $"({node.Name}{string.Join("", node.ChildNodes.ToList().Where(x => x.Name != "#comment").Select(x => make_string(x)))})";
msdp.Add(node, ms);
return ms;
}
μλ μΌμͺ½μ λ
ΈνΈ νΈλ¦¬κ° μ°μΈ‘μ ν¨ν΄ λ¬Έμμ΄λ‘ λ³νλλ μμ μ
λλ€.
#
μ λ¬Έμμ΄(#text
)μ κ°λ¦¬ν΅λλ€.
λ ν¨ν΄ λ¬Έμμ΄μ΄ μ΄λ μ λμ μ μ¬λλ₯Ό κ°μ§λ μ§λ₯Ό κ³μ°νκΈ° μν΄, λ κ°μ λ¬Έμμ΄μ μμΉ΄λ μ μ¬λλ₯Ό ꡬν©λλ€. λ λ²€μνμΈ μκ³ λ¦¬μ¦μ ν΅ν΄ λ λ¬Έμμ΄μ μ νμ μΈ μ°¨μ΄λ₯Ό κ³μ°ν μ μμΌλ©°, μ΄ μ°¨μ΄λ₯Ό κΈ΄ λ¬Έμμ΄μ κΈΈμ΄λ‘ λλμΌλ‘μ¨ μ μ¬λλ₯Ό ꡬν μ μμ΅λλ€.
public static int ComputeLevenshteinDistance(this string a, string b)
{
int x = a.Length;
int y = b.Length;
int i, j;
if (x == 0) return x;
if (y == 0) return y;
int[] v0 = new int[(y + 1) << 1];
for (i = 0; i < y + 1; i++) v0[i] = i;
for (i = 0; i < x; i++)
{
v0[y + 1] = i + 1;
for (j = 0; j < y; j++)
v0[y + j + 2] = Math.Min(Math.Min(v0[y + j + 1], v0[j + 1]) + 1, v0[j] + ((a[i] == b[j]) ? 0 : 1));
for (j = 0; j < y + 1; j++) v0[j] = v0[y + j + 1];
}
return v0[y + y + 1];
}
λ€μμ ν¨ν΄ λΉκ΅ μμ μ λλ€.
λΉκ΅ λμ ν¨ν΄: (tr#(td#)#(td#(a(em)#)#(a(span#))#)#(td#(span(em#))(a(img))#)#(td#)#(td#)#(td#)#)
μ νλ ν¨ν΄ λ΄μ©
( 64.2%) (tr#(td#)#(td(a(em)(b#)))#(td(b#))#(td#)#(td#)#(td#)#)
( 75.3%) (tr#(td#)#(td#(a(em)(b(b#)))#(a(span#))#)#(td#(b(b#))#)#(td#)#(td#)#(td#)#)
( 71.6%) (tr#(td#)#(td#(a(em)(b(b(font#))))#(a(span#))#)#(td#(b(b#))#)#(td#)#(td#)#(td#)#)
( 92.6%) (tr#(td#)#(td#(a(em)#)#(a(span#))#)#(td#(span(em#))(span#)#)#(td#)#(td#)#(td#)#)
(100.0%) (tr#(td#)#(td#(a(em)#)#(a(span#))#)#(td#(span(em#))(a(img))#)#(td#)#(td#)#(td#)#)
μμ μ΄λ€ λ Έλλ₯Ό μ νμΌλ‘ λνλ΄μ΄ λ€λ₯Έ λ Έλμμ μ μ¬λλ₯Ό λΉκ΅νλ μμ λ₯Ό μ€λͺ νμ΅λλ€. ν¨ν΄ λ§€μΉ κ³Όμ μ HTML μ΅μμ λ Έλμ λͺ¨λ λΆλΆ μ§ν©μ νμν΄ μ μ¬ν λ Έλλ€μ μ°Ύμ΅λλ€. μ΄λ μ¬μ©μ μ μμ λ°λΌ μ νλλ₯Ό μ€μ νμ¬ λΉμ·ν ν¨ν΄λ€λ μ°Ύμ μ μμ΅λλ€.
μΌμͺ½μ μ΄λ€ ν¨ν΄κ³Ό 100% μ μ¬λλ₯Ό κ°λ κ²½μ°λ₯Ό νμν κ²°κ³Όμ΄κ³ , μ€λ₯Έμͺ½μ 80% μ΄μμ μ μ¬λλ₯Ό κ°λ κ²½μ°λ₯Ό νμν κ²°κ³Όμ λλ€.
λ§μ½ ν¨ν΄λ€μ LCAκ° ν¨ν΄λ€μ νμλ
Έλλ‘ κ°λλ€λ©΄ λ°λ³΅λ¬Έμ ν΅ν μ κ·Όμ΄ κ°λ₯ν΄μ§λλ€.
2.2 μ
νλ¨μ μ½λλ₯Ό μ°Έκ³ ν΄λ³΄μΈμ. μ΄μ κ°μ μ½λλ₯Ό μ½κ² μμ±ν΄ λΌ μ μμ΅λλ€.
100%μ μ νλλ‘ ν¨ν΄μ μ°Ύμ κ²½μ°λΌλ©΄ λͺ¨λ κ³Όμ μ λͺ¨λ λ Έλμ μλ²½νκ² μ μ©μν¬ μ μμ§λ§, μ μ¬λκ° λ€λ₯Έ κ²λ€μ΄ μμ¬μλ€λ©΄ μ΄λ₯Ό λΆλ₯νλ κ³Όμ μ΄ νμν©λλ€.
μμ κ°μ΄ λκΈμ΄ νλ μ΄μ λ¬λ¦° κΈμλ λκΈμ κ°μκ° μ λͺ©μ νμλμ΄μμ§λ§, λκΈμ΄ μλ κ²½μ°μ νμλμ§ μμμ΅λλ€. λ°λΌμ λͺ¨λ λ Έλμ λν΄ λκΈμ κ°μλ₯Ό κ°μ Έμ€λ λΆλΆμ λ£λλ€λ©΄ μ€λ₯κ° μκΈΈ μ μμ΅λλ€. μ½λλ₯Ό μμ±νκΈ°μ μ μμ‘°μ¬λ₯Ό ν΅ν΄ μ΄λ¬ν μ΄κΈλ ν¨ν΄λ€μ λΆμνλ κ³Όμ μ΄ νμνλ©°, μ½λ μμ±μ μ΄λ₯Ό μ°Έκ³ ν΄ μ μ ν μ½λλ₯Ό μμ±ν μ μμ΄μΌ ν©λλ€.
λ€μμ ν¨ν΄ λΆμ μ 보μ μΌλΆμ λλ€.
-- Captures Info remove LCA Prefix --
@Number = /td[1]
@Icon = /td[2]/a[1]/em[1]
@Title = /td[2]/a[1]
@Comment = /td[2]/a[2]/span[1]
@Author = /td[3]
@WriteTime = /td[4]
@Views = /td[5]
@UpVote = /td[6]
-- Captures Info Origin --
@Number = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[1]
@Icon = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[2]/a[1]/em[1]
@Title = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[2]/a[1]
@Comment = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[2]/a[2]/span[1]
@Author = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[3]
@WriteTime = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[4]
@Views = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[5]
@UpVote = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[6]
-- Available Captures Info --
@Number = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[1]
@Icon = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[2]/a[1]/em[1]
@Title = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[2]/a[1]
@Author = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[3]
@WriteTime = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[4]
@Views = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[5]
@UpVote = /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]/td[6]
-- Pattern Info --
P-Summary: (tr#@Number#(td#@Title#(a@Comment)#)#@Author#@WriteTime#@Views#@UpVote#)
P-LCA: /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[4]
LCA: /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]
-- Capture result from Page --
Count: 40
...
-------------------------
test-case: #21
tc-lca: /html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[24]
@Number = 1257146
@Icon = /em:{class="icon_img icon_txt"}
@Title = κ·Όλ° μμ§ν κ°λ°μλ μνλκ±°μ? μ΄ν΄κ° μλ¨
@Comment = [6]
@Author = γ
γ
(106.101)
@WriteTime = 02.12
@Views = 48
@UpVote = 0
...
Available Captures Info
λ₯Ό 보면 @Comment
κ° λΉ μ Έμλ κ²μ λ³Ό μ μμ΅λλ€.
μ΄λ μ½λμμ±μ @Comment
λ₯Ό νΈλ€λ§ν μ μλ μ μ ν μ½λλ₯Ό μ½μ
νλΌλ μλ―Έλ‘ λ³Ό μ μμ΅λλ€.
μ΄μ μ μ 보λ₯Ό μ΄μ©ν΄ λ€μ μ½λλ₯Ό μ»μ μ μμ΅λλ€.
public class Pattern
{
public string Number;
public string Icon;
public string Title;
public string Comment;
public string Author;
public string WriteTime;
public string Views;
public string UpVote;
}
public List<Pattern> Extract(string html)
{
HtmlDocument document = new HtmlDocument();
document.LoadHtml(html);
var root_node = document.DocumentNode;
var result = List<Pattern>();
for (int i = 1; ; i++)
{
var node = root_node.SelectSingleNode($"/html[1]/body[1]/div[2]/div[2]/main[1]/section[1]/article[2]/div[2]/table[1]/tbody[1]/tr[{3+i*1}]");
var pattern = new Pattern();
if (node == null) break;
pattern.Number = node.SelectSingleNode("./td[1]").InnerText;
pattern.Icon = node.SelectSingleNode("./td[2]/a[1]/em[1]").InnerText;
pattern.Title = node.SelectSingleNode("./td[2]/a[1]").InnerText;
if (node.SelectSingleNode("./td[2]/a[2]/span[1]") != null)
pattern.Comment = node.SelectSingleNode("./td[2]/a[2]/span[1]").InnerText;
pattern.Author = node.SelectSingleNode("./td[3]").InnerText;
pattern.WriteTime = node.SelectSingleNode("./td[4]").InnerText;
pattern.Views = node.SelectSingleNode("./td[5]").InnerText;
pattern.UpVote = node.SelectSingleNode("./td[6]").InnerText;
result.Add(pattern);
}
return result;
}
μ°¨μ΄μ λΆμμ λ HTML
μ μ°¨μ΄μ μ λΆμνλ λ°©λ²μ
λλ€.
μ΄ κΈ°λ₯μ΄ νμν κ²½μ°μ μλ‘λ λ κ²μλ¬Όμ μ°¨μ΄μ μ λΆμν΄ μ λͺ©, κΈμ΄μ΄, λ³Έλ¬Έ λ±μ μ 보λ₯Ό
μλμΌλ‘ μ°Ύμλ΄λ κ²½μ° λ±μ΄ μμ΅λλ€. μ°¨μ΄μ λΆμμ μ¬λ¬ λ€λ₯Έ μ μ λΆμ λ°©λ²λ€μ΄λ κ°μ΄ μ¬μ©ν λ
μμ°μ±μ λμ± λν μ μμ κ²μΌλ‘ κΈ°λν©λλ€.
μ°¨μ΄μ λΆμμ κΈ°λ³Έμ μΈ μμ΄λμ΄λ λ§€μ° λ¨μνκ² λͺ¨λ λ Έλλ₯Ό μμλλ‘ λκ°μ΄ λ°©λ¬Ένμ¬ λ€λ₯Έ λΆλΆμ λͺ¨λ μ°Ύμλ κ²μ λλ€. λ§μ½ νκ·Έκ° λ€λ₯΄κ±°λ, μμ λ Έλμ κ°μκ° λ€λ₯΄λ€λ©΄ λμ΄μ λ°©λ¬Ένμ§ μμ΅λλ€. μ΄μ κ°μ΄ λ λ£¨νΈ λ Έλλ₯Ό λμμ λ°©λ¬Ένκ² λλ©΄ λ€μκ³Ό κ°μ λ€ κ°μ§ κ²½μ°μ μ°¨μ΄μ μ΄ λ°μν©λλ€.
1. νκ·Έκ° λ€λ₯Έ κ²½μ°
2. μμ±μ΄ λ€λ₯Έ κ²½μ°
3. μμ λ
Έλμ κ°μκ° λ€λ₯Έ κ²½μ°
4. ν¬ν¨λ ν
μ€νΈκ° λ€λ₯Έ κ²½μ°
νκ·Έκ° λ€λ₯Έ κ²½μ°λΌλ©΄ νμ λ
Έλλ€λ λͺ¨λ λ°λμμ κ°λ₯μ±μ΄ μμΌλ©°, μ΄λ μΉ νμ΄μ§λ₯Ό λΆλ¬ μ¬ λλ§λ€,
νΉμ λ€λ₯Έ URL Parameter
λ‘ μΉ νμ΄μ§λ₯Ό λ‘λ©ν λλ§λ€ λ€λ₯Έ λ
Έλꡬ쑰λ₯Ό κ°λ λ€λ μλ―Έλ‘ λ³Ό μ μμΌλ―λ‘,
λ°λΌμ μ΄ λΆλΆμ΄ μ λͺ©μ΄λ λ³Έλ¬Έκ°μ ν΅μ¬μ΄ λ λΆλΆμ΄ λ κ°λ₯μ±μ΄ λλ€λ κ²μ μλ―Έν©λλ€.
λ€λ§, νκ·Έκ° λ€λ₯Έ κ²½μ°κ° λ°μνλ κ²½μ°λ λ§€μ° λ§€μ° λλ¬Όλ€κ³ ν μ μμ΅λλ€.
μμ±μ΄ λ€λ₯Έ κ²½μ°λΌλ©΄ λ€λ₯Έ μΉ λ¦¬μμ€λ₯Ό λΆλ¬μ€λ κ²½μ°κ° λλΆλΆμ΄λ―λ‘(μλ₯Ό λ€μ΄ <img>
νκ·Έμ src
μμ±)
μ΄λ μΉ νμ΄μ§λ₯Ό λΆλ¬μ¬ λλ§λ€ λ¬λΌμ§ κ°λ₯μ±μ΄ λλ€λ κ²μ μλ―Έν©λλ€.
μμ λ Έλμ κ°μκ° λ€λ₯Έ κ²½μ°λ λΉμ·ν μ νμ λ μΉνμ΄μ§λ₯Ό λΆμνλ κ²½μ°μ κ±°μ λνλμ§ μλ μ°¨μ΄μ μ λλ€. μ¬κΈ°μ κ±°μλΌλ κ²μ λ§μμΌ λ κ° μ λμ΄κ³ , λ³΄ν΅ 0κ°λ 1κ°μμ μλ―Έν©λλ€. μ΄ λΆλΆμ΄ λ³Έλ¬ΈμΌ κ°λ₯μ±μ΄ κ°μ₯ λμ λΆλΆμ λλ€. λ°λΌμ λ³Έλ¬Έμ μ°Ύκ³ μΆλ€λ©΄ μμ λ Έλμ κ°μκ° λ€λ₯Έ κ²½μ°λ₯Ό λ¨Όμ μ΄ν΄λ³΄λκ² κ°μ₯ μ’μ λ°©λ²μ΄λΌκ³ ν μ μμ΅λλ€.
ν¬ν¨λ ν μ€νΈκ° λ€λ₯Έ κ²½μ°λ μΉ νμ΄μ§λ§λ€ λμΌν ꡬ쑰(μ€νμΌ)λ‘ UIκ° μ 곡λμ§λ§ κ·Έ μμ 컨ν μΈ κ° λ€λ₯΄λ€λ μλ―Έμ λλ€. λ°λΌμ μ λͺ©μ΄λ κΈμ΄μ΄μ κ°μ 컨ν μΈ λ€μ νμνκ³ μ ν λ μ΄ λΆλΆμ λ¨Όμ μ΄ν΄λ³΄λκ² μ’μ΅λλ€.
μ μ¬μ§μ ν¬ν¨λ ν μ€νΈκ° λ€λ₯Έ κ²½μ°μ μμ μ λλ€.
μλ μ¬μ§μ μμ λ Έλμ κ°μκ° λ€λ₯Έ 겨μ°μ μμ μ λλ€.