webcollector mysql_WebCollector爬取百度搜索引擎样例

package com.wjd.baidukey.crawler;

import java.io.ByteArrayInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.net.URLEncoder;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;

import java.util.TimeZone;

import org.apache.poi.poifs.filesystem.DirectoryEntry;

import org.apache.poi.poifs.filesystem.POIFSFileSystem;

import org.jsoup.nodes.Element;

import org.jsoup.select.Elements;

import cn.edu.hfut.dmic.contentextractor.ContentExtractor;

import cn.edu.hfut.dmic.webcollector.model.CrawlDatum;

import cn.edu.hfut.dmic.webcollector.model.CrawlDatums;

import cn.edu.hfut.dmic.webcollector.model.Page;

import cn.edu.hfut.dmic.webcollector.plugin.ram.RamCrawler;

public class BdiduKeywordCrawler extends RamCrawler{

private Connection connection;

private PreparedStatement pstatement;

// 连接MySql数据库。用户名root,密码mahao

String url = "jdbc:mysql://localhost:3306/wjd";

String username = "root";

String password = "mahao";

//保存抽取到的数据

StringBuilder result = new StringBuilder();

public BdiduKeywordCrawler(String keyword, int maxPageNum) throws Exception {

for (int pageNum = 1; pageNum <= maxPageNum; pageNum++) {

String url = createUrl(keyword, pageNum);

CrawlDatum datum = new CrawlDatum(url)

.putMetaData("keyword", keyword)

.putMetaData("pageNum", pageNum + "")

.putMetaData("pageType", "searchEngine")

.putMetaData("depth", "1");

addSeed(datum);

}

}

@Override

public void visit(Page page, CrawlDatums next) {

String keyword = page.getMetaData("keyword");

String pageType = page.getMetaData("pageType");

int depth = Integer.valueOf(page.getMetaData("depth"));

if (pageType.equals("searchEngine")) {

int pageNum = Integer.valueOf(page.getMetaData("pageNum"));

System.out.println("成功抓取关键词" + keyword + "的第" + pageNum + "页搜索结果");

// || div[class=result-op c-container xpath-log ]>h3>a

Elements results = page.select("div[class=result c-container ]>h3>a");

//Elements results1 = page.select("div[class=result-op c-container xpath-log]>h3>a");//,div[id=result-op c-container xpath-log]>h3>a

//System.out.println(results1.get(0));

//results.add(results1.get(0));

for (int rank = 0; rank < results.size(); rank++) {

Element result = results.get(rank);

/*

* 我们希望继续爬取每条搜索结果指向的网页,这里统称为外链。

* 我们希望在訪问外链时仍然能够知道外链处于搜索引擎的第几页、第几条,

* 所以将页号和排序信息放入兴许的CrawlDatum中,为了能够区分外链和

* 搜索引擎结果页面,我们将其pageType设置为outlink,这里的值全然由 用户定义。能够设置一个随意的值

* 在经典爬虫中,每一个网页都有一个refer信息。表示当前网页的链接来源。

* 比如我们首先訪问新浪首页。然后从新浪首页中解析出了新的新闻链接,

* 则这些网页的refer值都是新浪首页。WebCollector不直接保存refer值,

* 但我们能够通过以下的方式,将refer信息保存在metaData中。达到相同的效果。

* 经典爬虫中锚文本的存储也能够通过以下方式实现。

* 在一些需求中。希望得到当前页面在遍历树中的深度。利用metaData非常easy实现

* 这个功能,在将CrawlDatum加入到next中时,将其depth设置为当前訪问页面 的depth+1就可以。

*/

CrawlDatum datum = new CrawlDatum(result.attr("abs:href"))

.putMetaData("keyword", keyword)

.putMetaData("pageNum", pageNum + "")

.putMetaData("rank", rank + "")

.putMetaData("pageType", "outlink")

.putMetaData("depth", (depth + 1) + "")

.putMetaData("refer", page.getUrl());

next.add(datum);

}

} else if (pageType.equals("outlink")) {

/*int pageNum = Integer.valueOf(page.getMetaData("pageNum"));

int rank = Integer.valueOf(page.getMetaData("rank"));

String refer = page.getMetaData("refer");*/

try {

String content = ContentExtractor.getContentByUrl(page.getUrl());

/*String line = String.format(

"第%s页第%s个结果:标题:%s(%s字节)\tdepth=%s\trefer=%s", pageNum,

rank + 1, page.getDoc().title(), content,

depth, refer);*/

String line = String.format("标题:%s\n来源:%s\n正文:%s", page.getDoc().title(),page.getUrl(),content);

HashMap data = new HashMap();

Date currentDate = new java.util.Date();

SimpleDateFormat myFmt = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

TimeZone timeZoneChina = TimeZone.getTimeZone("Asia/Shanghai");// 获取中国的时区

myFmt.setTimeZone(timeZoneChina);// 设置系统时区

String grabTime = myFmt.format(currentDate);// new Date()为获取当前系统时间

data.put("title", page.getDoc().title());

data.put("from", page.getUrl());

data.put("content", content);

data.put("grabTime", grabTime);

//String line = String.format("标题:%s\n", page.getDoc().title());

//持久化到word文档中

//是否为线程安全???

//synchronized(this) {

String destFile = "D:\\"+"Result"+keyword+".doc";

result.append(line);

//将result写到doc文件里

write2File(destFile,result.toString());

//加入到数据库中

addResultData(data);

//}

System.out.println(line);

} catch (Exception e) {

//e.printStackTrace();

System.out.println("链接"+page.getUrl()+"失效");

}

}

}

//将数据保存到mysql数据库中

private void addResultData(HashMap data) {

String title = data.get("title");

String source_url = data.get("from");

String content = data.get("content").replaceAll("\\?{2,}", "");//去掉字符串中出现的多个连续问号。

//抓取时间

String grabTime = data.get("grabTime");

/*SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

Date date = null;

try {

date = format.parse(grabTime);

} catch (Exception e) {

e.printStackTrace();

}*/

//System.out.println("抓取时间"+grabTime);

try {

connection = DriverManager.getConnection(url, username,password);

String sql = "INSERT INTO wjd_keyword_search_table(TITLE,GRAP_TIME,CONTENT,SOURCE_URL) VALUES(?,?,?

,?

)";

String checkSql = "select 1 from wjd_keyword_search_table where TITLE='" + title + "'";

Statement statement = connection.prepareStatement(checkSql);

ResultSet result = statement.executeQuery(checkSql);

if (!result.next()) {

// 假设数据库中不存在该记录,则加入到数据库中

pstatement = connection.prepareStatement(sql);

pstatement.setString(1, title);

//pstatement.setString(2, date);

pstatement.setString(2,grabTime);

pstatement.setString(3, content);

pstatement.setString(4, source_url);

pstatement.executeUpdate();

}

} catch (SQLException e) {

e.printStackTrace();

}

}

/**

* 将数据持久化到本地doc文件里

* @param destFile

* @param line

*/

private void write2File(String destFile, String line) {

try {

//doc content

ByteArrayInputStream bais = new ByteArrayInputStream(line.getBytes());

POIFSFileSystem fs = new POIFSFileSystem();

DirectoryEntry directory = fs.getRoot();

directory.createDocument("WordDocument", bais);

FileOutputStream ostream = new FileOutputStream(destFile);

fs.writeFilesystem(ostream);

bais.close();

ostream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

public static void main(String[] args) throws Exception {

String[] keywordsList = {"网络爬虫","搜索引擎"};

int pageToal =5;

for (String keyword : keywordsList) {

BdiduKeywordCrawler crawler = new BdiduKeywordCrawler(keyword, pageToal);

crawler.start();

}

}

/**

* 依据关键词和页号拼接百度搜索相应的URL

*/

public static String createUrl(String keyword, int pageNum)

throws Exception {

int first = (pageNum-1) * 10;

keyword = URLEncoder.encode(keyword, "utf-8");

return String.format("https://www.baidu.com/s?

wd=%s&pn=%s",

keyword, first);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值