前几天公司要求我将数据库里的pages表里的title和sumarry列填充一下,这个表已经通过crawler填充了页面的url。所以我只要获取每个页面的url然后取得这个页面的内容就可以很容易取得某个字段,但是当中发生了一些问题。
1.获取页面的代码:
要用到以下类必须在pom.xml里加入下面的依赖:
<dependency>
<groupId>nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>0.9.5</version>
</dependency>
<dependency>
<artifactId>commons-httpclient</artifactId>
<groupId>commons-httpclient</groupId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>3.8</version>
</dependency>
判断页面字符集的方法:
/**
* Determine the page encoding from the binary stream
* @param is The source on which the process is executed.
* @return
*/
public String getCharset(InputStream is){
CharsetDetector detector;
CharsetMatch match;
detector = new CharsetDetector();
try {
BufferedInputStream inputStream = new BufferedInputStream(is);
detector.setText(inputStream);
} catch (Exception e1) {
e1.printStackTrace();
}
detector.enableInputFilter(true);
match = detector.detect();
String charset = match.getName();
return charset;
}
CharsetDetector 类是分析页面字符给出最可能的结果,比如百度百科的页面编码都是”gb2312"的,但是得出的结果为:GB18030,也即前者编码的超集。
获取页面内容代码:
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
public static byte[] downloadContent(String url) {
byte[] buffer = new byte[1024 * 100];
HttpClient httpClient = new HttpClient();
GetMethod getMethod = new GetMethod(url);
try {
int rt = httpClient.executeMethod(getMethod);
if (rt == HttpStatus.SC_OK) {
// int count = -1;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream responseBodyAsStream = getMethod.getResponseBodyAsStream();
while((count = responseBodyAsStream.read(buffer, 0, buffer.length)) > -1) {
baos.write(buffer, 0, count);
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
return baos.toByteArray();
}else {
return null;
}
} catch (Exception e) {
logger.error("error occur, while download page at the location of: " + url, e);
return null;
}finally {
getMethod.releaseConnection();
}
}
再看看ByteArrayOutputStream的API:
ByteArrayOutputStream
This class implements an output stream in which the data is written into a byte array. The buffer automatically grows as data is written to it. The data can be retrieved using toByteArray() and toString().
Closing a ByteArrayOutputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.
引用
The buffer automatically grows as data is written to it.
由于该类的buffer会自动增长,所以如果网页的大小超过预设的buffer大小的话它也能过这个特性来存放数据(除了网页的内容大的超过所剩内存大小,这时候就会出现OOM异常了)
一开始是直接返回一个InputStream,即getMethod.getResponseBodyAsStream();但是在另外一个类读这个stream的时候会报“attempted to read a closed stream",猜想应该是另外一个引用这个InputStream时被调用方法堆栈的对这个流的reference已经释放,所以才会抛出这个错误。因为这个原因,后来便直接在该方法中读出页面内容然后返回一个缓冲引用。
在返回缓冲的时候出了一个问题困扰了我好久。因为网页的大小会相差较大,所以100K的缓存有时候能一次性容纳一个网页,有时候必须要读好几次缓存才能获取所有页面的内容。一开始是直接return buffer,所以遇到小的页面是,所得的结果完全正确,而遇到大的页面超出缓存的大小时,这时候buffer的内容总是最后一次读取的大小,而前面读取的内容则被覆盖了,因此经常出现取不到title的情况。而用以上方法获取字符集的时候,也会因为数据不全而出现时对时错的情况。下次在获取诸如不确定大小数据的时候,一定要小心这个问题。
后来发现有一个类似的帖子:http://dengyin2000.iteye.com/blog/47417。
还想问一个问题,在获取description的时候,本人的代码是通过正则表达式来作的,如下:
public String getDescription(String page){
String description = null;
Pattern pattern = Pattern.compile("(<meta)(.*)name *= *[\"\'] *description *[\"\'](.*)(/>)", Pattern.CASE_INSENSITIVE );
Matcher matcher = pattern.matcher(page);
// boolean found = false;//flag indicating whether the page has a description.
String resultStr = null;
while(matcher.find()){
resultStr = matcher.group();
Pattern patternDesc = Pattern.compile("(content *= *[\"\'])(.*)([\"\'])", Pattern.CASE_INSENSITIVE);
Matcher matcherDesc = patternDesc.matcher(resultStr);
while(matcherDesc.find()){
description = matcherDesc.group(2);
}
// found = true;
}
//If no description found, then set title as its description
/*if(!found){
description = title;
}*/
return description;
}
在html中,一个tag里的attribute位置和个数不确定。在获取description时,通过查找是否有name=”description“的<meta/>字符串然。找到后再来查找content的attribute。这里用了两次正则表达式查找。不知道各位有没有更好的方法一个正则表达式就可以查出来的呢?
分享到:
相关推荐
动态加载通常是指通过JavaScript在页面加载之后异步获取数据并更新页面内容的技术。这种方式可以显著提高页面的首次加载速度,减少用户等待时间。 **面临的挑战:** 1. **数据获取困难:** 动态加载的数据往往不在...
这些页面规则解析涵盖了用户可能遇到的所有交互场景,确保了在不同情况下用户都能顺畅地获取信息和进行操作。 此外,规范还关注到用户个性化需求,如个人中心的设计,分为“我的提问”和“我的回答”两个子模块,让...
此外,由于网络爬虫涉及的法律和道德问题,务必确保你的行为合法,尊重网站的版权和用户隐私。 在Python爬虫的实际应用中,我们还可能遇到反爬虫策略,如验证码、IP限制等。为应对这些问题,我们可以使用代理IP、...
**MetInfo教程** MetInfo是一款专门为企业打造营销型网站的管理系统,...如果你在制作过程中遇到任何问题,可以访问教程网址(www.metinfo.cn/course)获取更多帮助,或者通过邮件(sales@metinfo.cn)联系支持团队。
**常见问题.rtf**文件可能包含了用户在使用Scrutiny时遇到的常见疑问和解答,对于新用户来说,这是一个很好的参考资源,可以帮助他们快速上手。 **TNT包使用教程.webloc**可能是指向一个教程的快捷方式,用户可以...
- **作用**:根据不同的状态值,可以判断页面是否被成功解析,以及解析过程中是否遇到了问题。 - **状态类型**: - **未解析**:表示页面还未开始解析。 - **解析成功**:表示页面解析完成并且没有遇到错误。 - *...
2. **元标签优化**:如标题标签(Title Tag)、描述标签(Meta Description)等,它们在搜索引擎结果页上展示,影响点击率。 3. **内容质量**:提供有价值、原创且与关键词相关的高质量内容,这是提升排名的关键。 ...
5. Meta元标签定制:灵活设置Title、Keyword和Description,提高搜索引擎理解网站内容的能力。 6. 物理路径和文件名自定义:适应不同的SEO策略,提升页面的友好性。 二、界面设计标准 1. 版块布局:设计清晰,主次...
9. **数据模型设计**: 设计合适的文档结构,以反映岗位信息的各个属性,如`{'title': '职位名称', 'description': '职位描述', 'requirements': '任职要求', ...}`,这有助于数据的管理和查询。 10. **异常处理**: ...
1. **关键词设置**:合理利用<title>、<meta name="description">和等标签来描述网页内容,有助于搜索引擎理解页面主题。 2. **内容质量**:高质量的内容是吸引用户和搜索引擎的关键。定期更新网站内容,并确保内容...
- `public navParams: NavParams`: 用于获取页面跳转时传递的参数。 4. **持久化数据** - **步骤1**: 使用`ionic generate provider Data`创建数据服务。 - **步骤2**: 在`app.module.ts`文件中导入并设置数据...
【RSS阅读器】是一种应用程序,它能够帮助用户订阅并管理RSS(Really Simple Syndication)源,从而方便地获取和阅读网络上的新闻、博客更新和其他在线内容。RSS是一种XML格式,用于发布和分享网站内容,使得用户...
在ASP代码中,也可以使用`On Error Resume Next`来启用错误处理,然后通过`Err.Description`获取错误信息。 6. 使用开发工具: 虽然ASP本身没有集成开发环境,但Visual Studio、Notepad++等编辑器支持ASP语法高亮...
#### 一、获取元素到页面左部和顶部的距离 在网页开发过程中,经常需要获取某个DOM元素相对于整个文档的位置信息,特别是它相对于文档左侧和顶部的距离。这些信息对于实现复杂的布局和交互功能非常有用。下面将详细...
SEO,即搜索引擎优化,是网络营销中的关键组成部分,它关乎到网站在搜索引擎结果页面上的排名,进而影响流量和潜在客户的获取。本资料集“一个SEO成长的经历和SEO面临的挑战”聚焦于这一主题,揭示了一个SEO从业者从...
通过上述介绍,我们了解了如何使用JS读取和解析Excel文件,以及在实际应用中可能遇到的问题和解决方案。虽然示例代码基于较旧的技术(如ActiveX),但在特定场景下仍然具有参考价值。在现代Web开发中,建议探索更...
`d`是一个包含feed信息的字典,包含了feed的元数据如title、link、description等,以及items(文章或条目)的信息。 2. 访问feed属性 解析后的结果可以直接通过键值访问,例如获取feed标题: ```python print(d....
网站RSS订阅功能插件RSSMaker ASP.NET版是一个用于在ASP.NET平台上实现RSS订阅功能的工具。...RSSMaker ASP.NET版通常会处理大部分兼容性问题,但开发者仍需了解基本的RSS标准,以便在遇到问题时进行排查和解决。
在手动编写自动化测试脚本时,只需要知道页面的标题(TITLE)和所需控件的`name`值即可编写测试用例。 **示例代码:** - 点击“百度一下,你就知道”页面中的“百度一下”按钮: ```vb Browser("百度一下,你就...
遇到问题时可通过官方渠道及时获取解答,确保网站顺利运行。此外,还附带了详尽的使用手册和安装指南,帮助新手快速上手。 #### 五、结语 总之,Progressio是一款集美观性与功能性于一体的优秀WordPress企业主题。...