#38 Change algorithm of SmartContentSelector
parent
296a68920e
commit
04fcf3193f
|
@ -23,7 +23,7 @@ public class OschinaBlogPageProcesser implements PageProcessor {
|
||||||
//skip this page
|
//skip this page
|
||||||
page.setSkip(true);
|
page.setSkip(true);
|
||||||
}
|
}
|
||||||
page.putField("content", page.getHtml().xpath("//div[@class='BlogContent']/tidyText()").toString());
|
page.putField("content", page.getHtml().smartContent().toString());
|
||||||
page.putField("tags", page.getHtml().xpath("//div[@class='BlogTags']/a/text()").all());
|
page.putField("tags", page.getHtml().xpath("//div[@class='BlogTags']/a/text()").all());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,100 +1,87 @@
|
||||||
package us.codecraft.webmagic.selector;
|
package us.codecraft.webmagic.selector;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.htmlcleaner.HtmlCleaner;
|
|
||||||
import org.htmlcleaner.TagNode;
|
|
||||||
import us.codecraft.webmagic.utils.Experimental;
|
import us.codecraft.webmagic.utils.Experimental;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the text content of html.<br>
|
* Borrowed from https://code.google.com/p/cx-extractor/
|
||||||
* Using Readability algorithm: find parents of all p tags.
|
|
||||||
*
|
*
|
||||||
* @author code4crafter@gmail.com <br>
|
* @author code4crafter@gmail.com <br>
|
||||||
* @since 0.1.0
|
* @since 0.4.1
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
@Experimental
|
@Experimental
|
||||||
public class SmartContentSelector implements Selector {
|
public class SmartContentSelector implements Selector {
|
||||||
|
|
||||||
private Logger logger = Logger.getLogger(getClass());
|
|
||||||
|
|
||||||
public SmartContentSelector() {
|
public SmartContentSelector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String select(String text) {
|
public String select(String html) {
|
||||||
HtmlCleaner htmlCleaner = new HtmlCleaner();
|
html = html.replaceAll("(?is)<!DOCTYPE.*?>", "");
|
||||||
TagNode tagNode = htmlCleaner.clean(text);
|
html = html.replaceAll("(?is)<!--.*?-->", ""); // remove html comment
|
||||||
if (tagNode == null) {
|
html = html.replaceAll("(?is)<script.*?>.*?</script>", ""); // remove javascript
|
||||||
return null;
|
html = html.replaceAll("(?is)<style.*?>.*?</style>", ""); // remove css
|
||||||
}
|
html = html.replaceAll("&.{2,5};|&#.{2,5};", " "); // remove special char
|
||||||
TagNode[] nodes = tagNode.getElementsByName("p", true);
|
html = html.replaceAll("(?is)<.*?>", "");
|
||||||
TagNode[] pres = tagNode.getElementsByName("pre", true);
|
List<String> lines;
|
||||||
Map<TagNode, Double> pDensityCountMap = new HashMap<TagNode, Double>();
|
int blocksWidth =3;
|
||||||
countPdensity(nodes, pDensityCountMap);
|
int threshold =86;
|
||||||
countPdensity(pres, pDensityCountMap);
|
int start;
|
||||||
for (TagNode pre : pres) {
|
int end;
|
||||||
addCounter(pre, pDensityCountMap, 2);
|
StringBuilder text = new StringBuilder();
|
||||||
}
|
ArrayList<Integer> indexDistribution = new ArrayList<Integer>();
|
||||||
List<Map.Entry<TagNode, Double>> sortList = new ArrayList<Map.Entry<TagNode, Double>>();
|
|
||||||
if (pDensityCountMap.size() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (Map.Entry<TagNode, Double> entry : pDensityCountMap.entrySet()) {
|
|
||||||
// if (logger.isDebugEnabled()) {
|
|
||||||
// logger.debug("p\t" + entry.getKey().getName() + "#" + entry.getKey().getAttributeByName("id") +
|
|
||||||
// "@" + entry.getKey().getAttributeByName("class") + ":" + entry.getValue());
|
|
||||||
// }
|
|
||||||
sortList.add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(sortList, new Comparator<Map.Entry<TagNode, Double>>() {
|
lines = Arrays.asList(html.split("\n"));
|
||||||
@Override
|
|
||||||
public int compare(Map.Entry<TagNode, Double> o1, Map.Entry<TagNode, Double> o2) {
|
for (int i = 0; i < lines.size() - blocksWidth; i++) {
|
||||||
Double d1 = o1.getValue();
|
int wordsNum = 0;
|
||||||
Double d2 = o2.getValue();
|
for (int j = i; j < i + blocksWidth; j++) {
|
||||||
return -d1.compareTo(d2);
|
lines.set(j, lines.get(j).replaceAll("\\s+", ""));
|
||||||
|
wordsNum += lines.get(j).length();
|
||||||
}
|
}
|
||||||
});
|
indexDistribution.add(wordsNum);
|
||||||
TagNode contentNode = sortList.get(0).getKey();
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("p\t" + contentNode.getName() + "#" + contentNode.getAttributeByName("id") +
|
|
||||||
"@" + contentNode.getAttributeByName("class"));
|
|
||||||
}
|
}
|
||||||
return htmlCleaner.getInnerHtml(contentNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addCounter(TagNode node, Map<TagNode, Double> countMap, double delta) {
|
start = -1; end = -1;
|
||||||
Double counter = countMap.get(node);
|
boolean boolstart = false, boolend = false;
|
||||||
if (counter == null) {
|
text.setLength(0);
|
||||||
countMap.put(node, delta);
|
|
||||||
} else {
|
|
||||||
countMap.put(node, counter + delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final double parentWeight = 0.7;
|
for (int i = 0; i < indexDistribution.size() - 1; i++) {
|
||||||
|
if (indexDistribution.get(i) > threshold && ! boolstart) {
|
||||||
private void countPdensity(TagNode[] nodes, Map<TagNode, Double> pDensityCountMap) {
|
if (indexDistribution.get(i+1).intValue() != 0
|
||||||
for (TagNode node : nodes) {
|
|| indexDistribution.get(i+2).intValue() != 0
|
||||||
if (node == null) {
|
|| indexDistribution.get(i+3).intValue() != 0) {
|
||||||
continue;
|
boolstart = true;
|
||||||
|
start = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TagNode parent = node.getParent();
|
if (boolstart) {
|
||||||
double pDensity = 1;
|
if (indexDistribution.get(i).intValue() == 0
|
||||||
while (parent != null) {
|
|| indexDistribution.get(i+1).intValue() == 0) {
|
||||||
addCounter(parent, pDensityCountMap, pDensity);
|
end = i;
|
||||||
parent = parent.getParent();
|
boolend = true;
|
||||||
pDensity = pDensity * parentWeight;
|
}
|
||||||
|
}
|
||||||
|
StringBuilder tmp = new StringBuilder();
|
||||||
|
if (boolend) {
|
||||||
|
//System.out.println(start+1 + "\t\t" + end+1);
|
||||||
|
for (int ii = start; ii <= end; ii++) {
|
||||||
|
if (lines.get(ii).length() < 5) continue;
|
||||||
|
tmp.append(lines.get(ii) + "\n");
|
||||||
|
}
|
||||||
|
String str = tmp.toString();
|
||||||
|
//System.out.println(str);
|
||||||
|
if (str.contains("Copyright") ) continue;
|
||||||
|
text.append(str);
|
||||||
|
boolstart = boolend = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return text.toString();
|
||||||
|
|
||||||
private TagNode findLowestCommonParent(List<TagNode> tagNodes, int maxMargin, Map<TagNode, AtomicInteger> countMap) {
|
|
||||||
TagNode contentNode = tagNodes.get(0);
|
|
||||||
return contentNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue