- 浏览: 1489088 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (525)
- SEO (16)
- JAVA-EE-Hibernate (6)
- JAVA-EE-Struts (29)
- JAVA-EE-Spring (15)
- Linux (37)
- JAVA-SE (29)
- NetWork (1)
- CMS (14)
- Semantic Research (3)
- RIA-Flex (0)
- Ajax-Extjs (4)
- Ajax-Jquery (1)
- www.godaddy.com (0)
- SSH (34)
- JavaScript (6)
- SoftwareEngineer (9)
- CMMI (0)
- IDE-Myeclipse (3)
- PHP (1)
- Algorithm (3)
- C/C++ (18)
- Concept&Items (2)
- Useful WebSite (1)
- ApacheServer (2)
- CodeReading (1)
- Socket (2)
- UML (10)
- PowerDesigner (1)
- Repository (19)
- MySQL (3)
- SqlServer (0)
- Society (1)
- Tomcat (7)
- WebService (5)
- JBoss (1)
- FCKeditor (1)
- PS/DW/CD/FW (0)
- DesignPattern (11)
- WebSite_Security (1)
- WordPress (5)
- WebConstruction (3)
- XML|XSD (7)
- Android (0)
- Project-In-Action (9)
- DatabaseDesign (3)
- taglib (7)
- DIV+CSS (10)
- Silverlight (52)
- JSON (7)
- VC++ (8)
- C# (8)
- LINQ (1)
- WCF&SOA (5)
- .NET (20)
- SOA (1)
- Mashup (2)
- RegEx (6)
- Psychology (5)
- Stock (1)
- Google (2)
- Interview (4)
- HTML5 (1)
- Marketing (4)
- Vaadin (2)
- Agile (2)
- Apache-common (6)
- ANTLR (0)
- REST (1)
- HtmlAnalysis (18)
- csv-export (3)
- Nucth (3)
- Xpath (1)
- Velocity (6)
- ASP.NET (9)
- Product (2)
- CSS (1)
最新评论
-
lt26w:
理解成门面模式应该比较容易明白吧
FacadePattern-Java代码实例讲解 -
lt26w:
看下面的例子比较明白.
FacadePattern-Java代码实例讲解 -
javaloverkehui:
这也叫文档,别逗我行吗,也就自己看看。
HtmlCleaner API -
SE_XiaoFeng:
至少也应该写个注释吧。
HtmlCleaner API -
jfzshandong:
...
org.springframework.web.filter.CharacterEncodingFilter 配置
我这次要介绍的是如何抽取正文,这部分是最为核心的.因为如果不能很好的提取原有文章的内容和样式,那么搜索出来的东西
就会惨不忍睹.根本就没有使用价值
在做正文抽取模块之前我曾经参考过很多抽取模式,有配置模版的,有搞视觉匹配的.有搞关键字识别的.我挨个做了分析
首先配置摸版是不太现实的,因为我在搜索技术资讯的时候,根本不知道会搜索到哪个网站,也根本没精力去配置摸版.所以这个行不通
基于视觉效果的分析,这个难度比较大,而且只适合于规范的网站,而现在很多网站根本不规范,广告链接漫天飞.人家都把最好的
位置留给广告了.而且我一直怀疑这个模式的可行性,它只是一个善意的推测.所以这方面没做过多尝试
我在想,是否有种简单的方法呢?难道就没有什么共性吗?
我想所有的正文应该有个共同的特点,那就是正文的长度应该超过其他文字组合的长度.很少会有一句话的正文,很少会有长度
短于标题的正文.所以这个应该成为一个突破口.
接下来,有一个很重要的问题,那段最长的正文在哪里呢?
肯定是在一个TABLE,或者DIV,或者ParagraphTag里.那好,那就找到那个包含文字最多的DIV或者TABLE.
不过问题又来了,HTML页面,经常是HTML元素的长度超过了正文的长度,有时候混入了不少的JAVASCRIPT.这些元素
HTMLPARSER经常会误认为是正文加以识别,导致很多正文竟然是一段JAVASCRIPT.
祛除杂质是一个关键,这里面要把那些HTML中常用的标签,以及连接中正文去除掉,否则,你搜索出来的很可能是别的什么,尤其
当正文文字相对较少的时候.我在搜索SOHU页面的时候就经常遇到这个问题,原因是SOHU的页面不是严格按照DIV布局,里面有很多广告
的JAVASCRIPT。新浪的有些页面也有这个现象,反到是一些中小网站的布局很规范,呵呵,真奇怪了。
做完这些工作后,我发现仍然有些网页不能正常抓取,原因是HTMLPARSER对TEXT的认识有问题.例如一段文字在
ParagraphTag中或者span中包含的,就不能很好的识别.所以要单独做个抽取ParagraphTag内容的函数.
做完这些步骤后,有一个问题出来了就是正文中包含的图片,连接,粗体,正常的表格.这些问题一个个的冒出来.既然问题出来了
那就要一个个的解决.解决了这些难题.我的网站抓取文章的质量就大大的提高了85%的准确率,基本达到实用阶段.我网站上的正文快照基本和原文保
持一致.
提供几个例子,大家可以看下原文和我抓取的有多少不同
1. http://www.itsubway.com/context/20071218/11762.htm
这个是单纯获取正文的例子,其中有粗体标签和链接
2 http://www.itsubway.com/context/20071218/12041.htm
这个是正文里混有图片和表格.
我把抽取正文的部分代码和大家共享.这些代码基本解决了我在上面列举出来的问题。包括正文中混有图片,连接,粗体,表格等。
大家要是有兴趣可以改造下这些代码 请大家重点看protected List extractHtml(Node nodeP,
PageContext context, String siteUrl)
这个函数是正文抽取的入口。我的这些函数写的不是很规范,别笑话!
/**
* 收集HTML页面信息 调用抓取函数 按照自己的摸版 生成网页
* @param url
* @param urlEncode
*/
public void makeContext(ChannelLinkDO c) {
String metakeywords = "<META content={0}
name=keywords>";
String metatitle = "<TITLE>{0}</TITLE>";
String metadesc = "<META content={0}
name=description>";
String netshap = "<p> 正文快照: 时间{0}</p> ";
String tempLeate = "<LI class=active><A
href=\"{0}\" target=_blank>{1}</A></LI>";
String crop = "<p><A href=\"{0}\"
target=_blank>{1}</A></p> ";
try {
String siteUrl = getLinkUrl(c.getLink());
Parser parser = new Parser(c.getLink());
parser.setEncoding(c.getEncode());
for (NodeIterator e = parser.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
if (node instanceof Html) {
PageContext context = new PageContext();
context.setNumber(0);
context.setTextBuffer(new StringBuffer());
//抓取出内容
extractHtml(node, context, siteUrl);
StringBuffer testContext =
context.getTextBuffer();
//.....生成网页
}
}
} catch (Exception e) {
System.out.println(e);
}
}
private String getLinkUrl(String link) {
String urlDomaiPattern = "(http://[^/]*?
" + "/)(.*?)";
Pattern pattern = Pattern.compile(urlDomaiPattern,
Pattern.CASE_INSENSITIVE + Pattern.DOTALL);
Matcher matcher = pattern.matcher(link);
String url = "";
while (matcher.find()) {
int start = matcher.start(1);
int end = matcher.end(1);
url = link.substring(start, end - 1).trim();
}
return url;
}
/**
* 递归钻取正文信息
* @param nodeP
* @return
*/
protected List extractHtml(Node nodeP, PageContext context,
String siteUrl)
throws Exception {
NodeList nodeList = nodeP.getChildren();
boolean bl = false;
if ((nodeList == null) || (nodeList.size() == 0)) {
if (nodeP instanceof ParagraphTag) {
ArrayList tableList = new ArrayList();
StringBuffer temp = new StringBuffer();
temp.append("<p style=\"TEXT-INDENT: 2em\">");
tableList.add(temp);
temp = new StringBuffer();
temp.append("</p>").append(lineSign);
tableList.add(temp);
return tableList;
}
return null;
}
if ((nodeP instanceof TableTag) || (nodeP instanceof Div)) {
bl = true;
}
if (nodeP instanceof ParagraphTag) {
ArrayList tableList = new ArrayList();
StringBuffer temp = new StringBuffer();
temp.append("<p style=\"TEXT-INDENT: 2em\">");
tableList.add(temp);
extractParagraph(nodeP, siteUrl, tableList);
temp = new StringBuffer();
temp.append("</p>").append(lineSign);
tableList.add(temp);
return tableList;
}
ArrayList tableList = new ArrayList();
try {
for (NodeIterator e = nodeList.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
if (node instanceof LinkTag) {
tableList.add(node);
setLinkImg(node, siteUrl);
} else if (node instanceof ImageTag) {
ImageTag img = (ImageTag) node;
if
(img.getImageURL().toLowerCase().indexOf("http://") < 0) {
img.setImageURL(siteUrl +
img.getImageURL());
} else {
img.setImageURL(img.getImageURL());
}
tableList.add(node);
} else if (node instanceof ScriptTag ||
node instanceof StyleTag || node instanceof
SelectTag) {
} else if (node instanceof TextNode) {
if (node.getText().length() > 0) {
StringBuffer temp = new StringBuffer();
String text = collapse(node.getText()
.replaceAll(" ", "")
.replaceAll(" ",
""));
temp.append(text.trim());
tableList.add(temp);
}
} else {
if (node instanceof TableTag || node instanceof
Div) {
TableValid tableValid = new TableValid();
isValidTable(node, tableValid);
if (tableValid.getTrnum() > 2) {
tableList.add(node);
continue;
}
}
List tempList = extractHtml(node, context,
siteUrl);
if ((tempList != null) &&
(tempList.size() > 0)) {
Iterator ti = tempList.iterator();
while (ti.hasNext()) {
tableList.add(ti.next());
}
}
}
}
} catch (Exception e) {
return null;
}
if ((tableList != null) && (tableList.size() >
0)) {
if (bl) {
StringBuffer temp = new StringBuffer();
Iterator ti = tableList.iterator();
int wordSize = 0;
StringBuffer node;
int status = 0;
StringBuffer lineStart = new StringBuffer(
"<p style=\"TEXT-INDENT: 2em\">");
StringBuffer lineEnd = new StringBuffer("</p>"
+ lineSign);
while (ti.hasNext()) {
Object k = ti.next();
if (k instanceof LinkTag) {
if (status == 0) {
temp.append(lineStart);
status = 1;
}
node = new StringBuffer(((LinkTag)
k).toHtml());
temp.append(node);
} else if (k instanceof ImageTag) {
if (status == 0) {
temp.append(lineStart);
status = 1;
}
node = new StringBuffer(((ImageTag)
k).toHtml());
temp.append(node);
} else if (k instanceof TableTag) {
if (status == 0) {
temp.append(lineStart);
status = 1;
}
node = new StringBuffer(((TableTag)
k).toHtml());
temp.append(node);
} else if (k instanceof Div) {
if (status == 0) {
temp.append(lineStart);
status = 1;
}
node = new StringBuffer(((Div) k).toHtml());
temp.append(node);
} else {
node = (StringBuffer) k;
if (status == 0) {
if (node.indexOf("<p") < 0) {
temp.append(lineStart);
temp.append(node);
wordSize = wordSize + node.length();
status = 1;
} else {
temp.append(node);
status = 1;
}
} else if (status == 1) {
if (node.indexOf("</p") < 0) {
if (node.indexOf("<p") < 0) {
temp.append(node);
wordSize = wordSize +
node.length();
} else {
temp.append(lineEnd);
temp.append(node);
status = 1;
}
} else {
temp.append(node);
status = 0;
}
}
}
}
if (status == 1) {
temp.append(lineEnd);
}
if (wordSize > context.getNumber()) {
context.setNumber(wordSize);
context.setTextBuffer(temp);
}
return null;
} else {
return tableList;
}
}
return null;
}
/**
* 设置图象连接
* @param nodeP
* @param siteUrl
*/
private void setLinkImg(Node nodeP, String siteUrl) {
NodeList nodeList = nodeP.getChildren();
try {
for (NodeIterator e = nodeList.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
if (node instanceof ImageTag) {
ImageTag img = (ImageTag) node;
if
(img.getImageURL().toLowerCase().indexOf("http://") < 0) {
img.setImageURL(siteUrl +
img.getImageURL());
} else {
img.setImageURL(img.getImageURL());
}
}
}
} catch (Exception e) {
return;
}
return;
}
/**
* 钻取段落中的内容
* @param nodeP
* @param siteUrl
* @param tableList
* @return
*/
private List extractParagraph(Node nodeP, String siteUrl, List
tableList) {
NodeList nodeList = nodeP.getChildren();
if ((nodeList == null) || (nodeList.size() == 0)) {
if (nodeP instanceof ParagraphTag) {
StringBuffer temp = new StringBuffer();
temp.append("<p style=\"TEXT-INDENT: 2em\">");
tableList.add(temp);
temp = new StringBuffer();
temp.append("</p>").append(lineSign);
tableList.add(temp);
return tableList;
}
return null;
}
try {
for (NodeIterator e = nodeList.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
if (node instanceof ScriptTag || node instanceof
StyleTag ||
node instanceof SelectTag) {
} else if (node instanceof LinkTag) {
tableList.add(node);
setLinkImg(node, siteUrl);
} else if (node instanceof ImageTag) {
ImageTag img = (ImageTag) node;
if
(img.getImageURL().toLowerCase().indexOf("http://") < 0) {
img.setImageURL(siteUrl +
img.getImageURL());
} else {
img.setImageURL(img.getImageURL());
}
tableList.add(node);
} else if (node instanceof TextNode) {
if (node.getText().trim().length() > 0) {
String text = collapse(node.getText()
.replaceAll(" ", "")
.replaceAll(" ",
""));
StringBuffer temp = new StringBuffer();
temp.append(text);
tableList.add(temp);
}
} else if (node instanceof Span) {
StringBuffer spanWord = new StringBuffer();
getSpanWord(node, spanWord);
if ((spanWord != null) &&
(spanWord.length() > 0)) {
String text = collapse(spanWord.toString()
.replaceAll(" ", "")
.replaceAll(" ", ""));
StringBuffer temp = new StringBuffer();
temp.append(text);
tableList.add(temp);
}
} else if (node instanceof TagNode) {
String tag = node.toHtml();
if (tag.length() <= 10) {
tag = tag.toLowerCase();
if ((tag.indexOf("strong") >= 0) ||
(tag.indexOf("b") >= 0)) {
StringBuffer temp = new StringBuffer();
temp.append(tag);
tableList.add(temp);
}
} else {
if (node instanceof TableTag || node
instanceof Div) {
TableValid tableValid = new
TableValid();
isValidTable(node, tableValid);
if (tableValid.getTrnum() > 2) {
tableList.add(node);
continue;
}
}
extractParagraph(node, siteUrl, tableList);
}
}
}
} catch (Exception e) {
return null;
}
return tableList;
}
protected void getSpanWord(Node nodeP, StringBuffer spanWord) {
NodeList nodeList = nodeP.getChildren();
try {
for (NodeIterator e = nodeList.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
if (node instanceof ScriptTag || node instanceof
StyleTag ||
node instanceof SelectTag) {
} else if (node instanceof TextNode) {
spanWord.append(node.getText());
} else if (node instanceof Span) {
getSpanWord(node, spanWord);
} else if (node instanceof ParagraphTag) {
getSpanWord(node, spanWord);
} else if (node instanceof TagNode) {
String tag = node.toHtml().toLowerCase();
if (tag.length() <= 10) {
if ((tag.indexOf("strong") >= 0) ||
(tag.indexOf("b") >= 0)) {
spanWord.append(tag);
}
}
}
}
} catch (Exception e) {
}
return;
}
/**
* 判断TABLE是否是表单
* @param nodeP
* @return
*/
private void isValidTable(Node nodeP, TableValid tableValid) {
NodeList nodeList = nodeP.getChildren();
/**如果该表单没有子节点则返回**/
if ((nodeList == null) || (nodeList.size() == 0)) {
return;
}
try {
for (NodeIterator e = nodeList.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
/**如果子节点本身也是表单则返回**/
if (node instanceof TableTag || node instanceof Div)
{
return;
} else if (node instanceof ScriptTag ||
node instanceof StyleTag || node instanceof
SelectTag) {
return;
} else if (node instanceof TableColumn) {
return;
} else if (node instanceof TableRow) {
TableColumnValid tcValid = new
TableColumnValid();
tcValid.setValid(true);
findTD(node, tcValid);
if (tcValid.isValid()) {
if (tcValid.getTdNum() < 2) {
if (tableValid.getTdnum() > 0) {
return;
} else {
continue;
}
} else {
if (tableValid.getTdnum() == 0) {
tableValid.setTdnum(tcValid.getTdNum());
tableValid.setTrnum(tableValid.getTrnum() + 1);
} else {
if (tableValid.getTdnum() ==
tcValid.getTdNum()) {
tableValid.setTrnum(tableValid.getTrnum() +
1);
} else {
return;
}
}
}
}
} else {
isValidTable(node, tableValid);
}
}
} catch (Exception e) {
return;
}
return;
}
/**
* 判断是否有效TR
* @param nodeP
* @param TcValid
* @return
*/
private void findTD(Node nodeP, TableColumnValid tcValid) {
NodeList nodeList = nodeP.getChildren();
/**如果该表单没有子节点则返回**/
if ((nodeList == null) || (nodeList.size() == 0)) {
return;
}
try {
for (NodeIterator e = nodeList.elements();
e.hasMoreNodes();) {
Node node = (Node) e.nextNode();
/**如果有嵌套表单**/
if (node instanceof TableTag || node instanceof Div
||
node instanceof TableRow ||
node instanceof TableHeader) {
tcValid.setValid(false);
return;
} else if (node instanceof ScriptTag ||
node instanceof StyleTag || node instanceof
SelectTag) {
tcValid.setValid(false);
return;
} else if (node instanceof TableColumn) {
tcValid.setTdNum(tcValid.getTdNum() + 1);
} else {
findTD(node, tcValid);
}
}
} catch (Exception e) {
tcValid.setValid(false);
return;
}
return;
}
protected String collapse(String string) {
int chars;
int length;
int state;
char character;
StringBuffer buffer = new StringBuffer();
chars = string.length();
if (0 != chars) {
length = buffer.length();
state = ((0 == length) || (buffer.charAt(length - 1) == '
') ||
((lineSign_size <= length) &&
buffer.substring(length - lineSign_size,
length).equals(lineSign)))
? 0 : 1;
for (int i = 0; i < chars; i++) {
character = string.charAt(i);
switch (character) {
case '\u0020':
case '\u0009':
case '\u000C':
case '\u200B':
case '\u00a0':
case '\r':
case '\n':
if (0 != state) {
state = 1;
}
break;
default:
if (1 == state) {
buffer.append(' ');
}
state = 2;
buffer.append(character);
}
}
}
return buffer.toString();
}
- 正文抽取.rar (5.9 KB)
- 下载次数: 31
发表评论
-
htmlunit 示例
2010-08-20 18:40 4310先下载依赖的相关JAR包:http://sourcefor ... -
HTMLParser的两种使用方法
2010-04-15 16:37 5372HTMLParser的两种使用方法 ... -
HtmlCleanner结合xpath用法
2010-04-15 13:24 3522文章分类:Java编程 ... -
基于Htmlparser的天气预报程序(续)
2010-04-14 13:53 1066zz:http://www.iteye.com/topic/6 ... -
httpclient(校内网)
2010-04-13 15:10 1271Java code <!-- C ... -
httpclient(校内网)
2010-04-13 15:10 1396httpclient(校内网),大家帮忙看看我的 http ... -
HTTPClient模拟登陆人人网
2010-04-13 14:58 1873zz: 目的: http://www.iteye. ... -
HtmlCleaner API
2010-04-13 13:40 4455HtmlCleaner API Create cleaner ... -
htmlcleaner惯用法
2010-04-13 13:39 1421Common usage Tipically the f ... -
htmlcleaner惯用法
2010-04-13 13:39 1498Common usage Tipically t ... -
htmlcleaner 使用示例.
2010-04-13 13:10 10004原文出处:http://blog.chenlb.com/200 ... -
http://htmlparser.com.cn/
2010-04-12 16:20 1030http://htmlparser.com.cn/ ... -
开源网络蜘蛛spider(转载)
2010-04-12 15:42 1308spider是搜索引擎的必须 ... -
基于Spindle的增强HTTP Spider
2010-04-12 15:33 1455zz:http://www.iteye.com/news ... -
Cobra: Java HTML 解析器
2010-04-12 15:32 2913Cobra 简介: Cobra是一个 ... -
HtmlParser初步研究
2010-04-12 15:18 906目的是快速入手,而不 ... -
基于Htmlparser的天气预报程序
2010-04-12 15:16 1055htmlparser是一个纯的java写的html解析的库,它 ...
相关推荐
本方法中用到了网页分析器htmlparser,采用Java语言编程,工具是eclipse。可以实现把正文放在table结点的HTML网页的正文信息抽取功能。
htmlparser.net是一个c#写的html解析的库,主要用于改造或提取html。它能超高速解析html,而且不会出错。 毫不夸张地说,htmlparser就是目前最好的html解析和分析的工具。
使用非极大值抑制法确定镜头边界系数极大值并排序,以实现基于镜头边界系数的关键帧提取 JMF(Java视频处理): 功能 a)在Java Applet和应用程序中播放贵重物品媒体文件,如AVI、MPEG、WAV等; b)可以播放从互联网...
得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
JCaptcha4Struts2 是一个 Struts2的插件,用来增加验证码的支持,使用时只需要用一个 JSP 标签 (<jcaptcha:image label="Type the text "/> ) 即可,直接在 struts.xml 中进行配置,使用强大的 JCaptcha来生成验证码...
得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥验证签名结果,使用公钥初始化签名对象,用于...