java实现简单的网络爬虫(爬取电影天堂电影信息)
来源:互联网 发布:汽车理论考试软件 编辑:程序博客网 时间:2024/05/04 11:34
在最开始,我们要在网上下载所用到的jar包,应为这只是一个简单的网络爬虫所以很多包里的内容没有用到。
下面几个包就可以了。并且要引入这些包。
主类Bigdata.java
import org.htmlparser.util.ParserException;public class Bigdata {public static void main(String[] args) throws ParserException {String url = "http://www.dytt8.net"; System.out.println("开始爬取网页"); MyCrawler crawler = new MyCrawler(url); crawler.crawling(new String[] { url },url);
这个雷氏负责下载成为文本文件的类:
import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.lang.reflect.Method;import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;import org.apache.commons.httpclient.HttpClient;import org.apache.commons.httpclient.HttpException;import org.apache.commons.httpclient.HttpStatus;import org.apache.commons.httpclient.methods.GetMethod;import org.apache.commons.httpclient.params.HttpMethodParams;public class DownLoadFile {//重命名 /** * 根据 url 和网页类型生成需要保存的网页的文件名 去除掉 url 中非文件名字符 */ public String getFileNameByUrl(String url, String contentType) { // remove http:// url = url.substring(7); // text/html类型 if (contentType.indexOf("html") != -1) {//字符串中没有html url = url.replaceAll("[\\?/:*|<>\"]", "_") + ".txt";//将正则表达式中的那些字符替换成— return url; } // 如application/pdf类型 else { return url.replaceAll("[\\?/:*|<>\"]", "_") + "." + contentType.substring(contentType.lastIndexOf("/") + 1); } } /** * 保存网页字节数组到本地文件 filePath 为要保存的文件的相对地址 */ private void saveToLocal(byte[] data, String filePath,String url) {//保存 try { DataOutputStream out = new DataOutputStream(new FileOutputStream( new File(filePath),true)); out.writeBytes(url+" "); for (int i = 0; i < data.length; i++){ out.write(data[i]); } out.writeBytes("\r\n"); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } /* 下载 url 指向的网页 */ public String downloadfile(String url,byte[] responseBody,String url1) {//下载 String filePath = null; /* 1.生成 HttpClinet 对象并设置参数 */ HttpClient httpClient = new HttpClient(); // 设置 Http 连接超时 5s httpClient.getHttpConnectionManager().getParams() .setConnectionTimeout(2000); /* 2.生成 GetMethod 对象并设置参数 */ GetMethod getMethod = new GetMethod(url); // 设置 get 请求超时 5s getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 2000); // 设置请求重试处理 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler()); /* 3.执行 HTTP GET 请求 */ try { int statusCode = httpClient.executeMethod(getMethod); // 判断访问的状态码 if (statusCode != HttpStatus.SC_OK) { System.err.println("Method failed: " + getMethod.getStatusLine()); filePath = null; } /* 4.处理 HTTP 响应内容 */ // 根据网页 url 生成保存时的文件名 filePath = "d:\\spider\\"+url1 +".txt"; /*+ getFileNameByUrl(url, getMethod.getResponseHeader("Content-Type") .getValue());*/ saveToLocal(responseBody, filePath,url); } catch (HttpException e) { // 发生致命的异常,可能是协议不对或者返回的内容有问题 System.out.println("Please check your provided http address!"); e.printStackTrace(); } catch (IOException e) { // 发生网络异常 e.printStackTrace(); } finally { // 释放连接 getMethod.releaseConnection(); } return filePath; }}这个类是解析类工具类
import java.awt.SystemColor;import java.util.HashSet;import java.util.Set;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.htmlparser.Node;import org.htmlparser.NodeFilter;import org.htmlparser.Parser;import org.htmlparser.Remark;import org.htmlparser.Tag;import org.htmlparser.Text;import org.htmlparser.filters.NodeClassFilter;import org.htmlparser.filters.OrFilter;import org.htmlparser.filters.TagNameFilter;import org.htmlparser.tags.LinkTag;import org.htmlparser.tags.ParagraphTag;import org.htmlparser.tags.TitleTag;import org.htmlparser.util.NodeList;import org.htmlparser.util.ParserException;import org.htmlparser.visitors.NodeVisitor;import testchartset.Testchartset;public class HtmlParserTool { // 获取一个网站上的链接,filter 用来过滤链接 public static Set<String> extracLinks(String url, LinkFilter filter,String url2) { Set<String> links = new HashSet<String>(); try { Parser parser = new Parser(url); parser.setEncoding(Testchartset.dectedCode(url)); //parser.setEncoding("gb2312"); /*NodeFilter filtercode = new TagNameFilter("META"); NodeFilter filtercode1 = new TagNameFilter("meta"); OrFilter linkFilter1 = new OrFilter(filtercode, filtercode1); NodeList node = parser.extractAllNodesThatMatch(linkFilter1); Node matanode = (Node) node.elementAt(0); String code = matanode.getText(); int start1 = code.indexOf("charset="); code = code.substring(start1); //int end1 = code.indexOf(" "); //if (end1 == -1) //end1 = code.indexOf(">"); String encode = code.substring(8, code.length() - 1); System.out.println(encode); parser.setEncoding(encode);*/ // 过滤 <frame >标签的 filter,用来提取 frame 标签里的 src 属性所表示的链接 NodeFilter frameFilter = new NodeFilter() {public boolean accept(Node node) { if (node.getText().startsWith("frame src=")) { //System.out.println("true"); return true; } else { //System.out.println("flase"); return false; } } }; // OrFilter 来设置过滤 <a> 标签,和 <frame> 标签 OrFilter linkFilter = new OrFilter(new NodeClassFilter( LinkTag.class), frameFilter); // 得到所有经过过滤的标签 NodeList list = parser.extractAllNodesThatMatch(linkFilter); for (int i = 0; i < list.size(); i++) { Node tag = list.elementAt(i); if (tag instanceof LinkTag)// <a> 标签 { //System.out.println(tag.getText()); LinkTag link = (LinkTag) tag; String linkUrl = link.getLink();// url if(linkUrl.startsWith(url2)){ } else{ if(linkUrl.startsWith("ftp")){ linkUrl=null; }else{ linkUrl = url2+linkUrl; } } //System.out.println(linkUrl); //System.out.println(linkUrl); //if (filter.accept(linkUrl)) //System.out.println(linkUrl); if(linkUrl!=null) links.add(linkUrl); } else// <frame> 标签 { // 提取 frame 里 src 属性的链接如 <frame src="test.html"/> String frame = tag.getText(); //System.out.println(frame); int start = frame.indexOf("src="); //System.out.println(start); frame = frame.substring(start); int end = frame.indexOf(" "); if (end == -1) end = frame.indexOf(">"); String frameUrl = frame.substring(5, end - 1); if (filter.accept(frameUrl)) links.add(frameUrl); } } } catch (ParserException e) { e.printStackTrace(); } return links; } public static byte[] paerserhtml(String url, LinkFilter filter){ //byte[] content = null; String context = null; Parser parser; Pattern p = Pattern.compile("\\s*|\t|\r|\n"); try {parser = new Parser(url); //parser.setEncoding("gb2312"); parser.setEncoding(Testchartset.dectedCode(url)); NodeFilter filter1 = new TagNameFilter ("title"); //NodeList nodes = parser.extractAllNodesThatMatch(filter1); NodeFilter filter2 = new TagNameFilter ("div"); OrFilter linkFilter = new OrFilter(filter1, filter2); NodeList nodes = parser.extractAllNodesThatMatch(linkFilter); if(nodes!=null) { for (int i = 0; i < nodes.size(); i++) { Node textnode = (Node) nodes.elementAt(i); String line = textnode.getText(); //System.out.println(line); String text = textnode.toPlainTextString(); //System.out.println(text); if(line.contains("Zoom")){ //System.out.println(line.replaceAll(" ", "").replaceAll("\n", "")); Matcher m = p.matcher(text); String t = m.replaceAll(""); context += t; context += "\n"; }/*else{ context += text; }*/ // if(textnode.getText() //context += textnode.toPlainTextString(); //context += textnode.getText(); } //System.out.println(context); } /*NodeFilter filter2 = new TagNameFilter ("div"); NodeFilter filter3 = new TagNameFilter ("img"); OrFilter linkFilter = new OrFilter(filter3, filter2); NodeList nodes_context = parser.extractAllNodesThatMatch(linkFilter); if(nodes_context!=null) { for (int i = 0; i < nodes_context.size(); i++) { Node textnode_context = (Node) nodes_context.elementAt(i); context += textnode_context.toPlainTextString(); context += textnode_context.getText(); } } else{ System.out.println("null"); }*/} catch (ParserException e) {// TODO 自动生成的 catch 块e.printStackTrace();}finally{}if(context==null){context = "页面找不到了";return context.getBytes();}else{public interface LinkFilter { public boolean accept(String url); }
return context.getBytes(); } } }定义一个接口public interface LinkFilter { public boolean accept(String url); }队列类import java.util.HashSet;import java.util.PriorityQueue;import java.util.Set;import java.util.Queue;public class LinkQueue { // 已访问的 url 集合 private static Set visitedUrl = new HashSet(); // 待访问的 url 集合 private static Queue unVisitedUrl = new PriorityQueue(); // 获得URL队列 public static Queue getUnVisitedUrl() { return unVisitedUrl; } // 添加到访问过的URL队列中 public static void addVisitedUrl(String url) { visitedUrl.add(url); } // 移除访问过的URL public static void removeVisitedUrl(String url) { visitedUrl.remove(url); } // 未访问的URL出队列 public static Object unVisitedUrlDeQueue() { return unVisitedUrl.poll(); } // 保证每个 url 只被访问一次 public static void addUnvisitedUrl(String url) { if (url != null && !url.trim().equals("") && !visitedUrl.contains(url) && !unVisitedUrl.contains(url)) unVisitedUrl.add(url); } // 获得已经访问的URL数目 public static int getVisitedUrlNum() { return visitedUrl.size(); } // 判断未访问的URL队列中是否为空 public static boolean unVisitedUrlsEmpty() { return unVisitedUrl.isEmpty(); }}爬虫类import java.util.Set;import org.htmlparser.util.ParserException;public class MyCrawler { /** * 使用种子初始化 URL 队列 * * @return * @param seeds * 种子URL */privateString url1 = null; private void initCrawlerWithSeeds(String[] seeds) { for (int i = 0; i < seeds.length; i++) LinkQueue.addUnvisitedUrl(seeds[i]); } public MyCrawler(String url){//构造函数 this.url1 = url.replaceAll("[\\?/:*|<>\"]", "_"); } /** * 抓取过程 * * @return * @param seeds * @throws ParserException */ public void crawling(String[] seeds,final String url2) throws ParserException { // 定义过滤器,提取以http://www.lietu.com开头的链接 LinkFilter filter = new LinkFilter() { public boolean accept(String url) { if (url.startsWith(url2)) return true; else return false; } }; // 初始化 URL 队列 initCrawlerWithSeeds(seeds); // 循环条件:待抓取的链接不空且抓取的网页不多于1000 while (!LinkQueue.unVisitedUrlsEmpty() && LinkQueue.getVisitedUrlNum() <= 10000000) { // 队头URL出队列 String visitUrl = (String) LinkQueue.unVisitedUrlDeQueue(); byte[] context = HtmlParserTool.paerserhtml(visitUrl, filter); System.out.println(LinkQueue.getVisitedUrlNum()); if (visitUrl == null) continue; DownLoadFile downLoader = new DownLoadFile(); // 下载网页 //System.out.println(context.toString()); downLoader.downloadfile(visitUrl,context,url1); // 该 url 放入到已访问的 URL 中 LinkQueue.addVisitedUrl(visitUrl); // 提取出下载网页中的 URL Set<String> links = HtmlParserTool.extracLinks(visitUrl, filter,url2); // 新的未访问的 URL 入队 for (String link : links) { LinkQueue.addUnvisitedUrl(link); } } }}下面这个类有点特殊也有不完善的地方,是一个解析网页编码的类获得网页到底是什么编码的,然后在告诉下载器解析器以什么编码解析下载中文。应为电影天堂网站所有网页都是gb2312编码的所以我就为了成功率注释掉了代码改为只返回gb2312编码。以后改好了是可以适应任何一种编码的。import org.htmlparser.Node;import org.htmlparser.NodeFilter;import org.htmlparser.Parser;import org.htmlparser.filters.OrFilter;import org.htmlparser.filters.TagNameFilter;import org.htmlparser.tags.BodyTag;import org.htmlparser.tags.Html;import org.htmlparser.util.NodeIterator;import org.htmlparser.util.NodeList;public class Testchartset{private static final String oriEncode = "UTF-8,utf-8,gb2312,gbk,iso-8859-1";public static void main(String [] args){String url="http://www.dytt8.net/";String decode=dectedCode(url);System.out.println(decode);}/** * 检测字符级 * @param url * @return */ /*public static String dectedEncode(String url) { String[] encodes = oriEncode.split(","); for (int i = 0; i < encodes.length; i++) { if (dectedCode(url, encodes[i])) { return encodes[i]; } } return null; }*/ public static String dectedCode(String url) { /*try { Parser parser = new Parser(url); //parser.setEncoding(encode); NodeFilter filtercode = new TagNameFilter("META"); NodeFilter filtercode1 = new TagNameFilter("meta"); OrFilter linkFilter = new OrFilter(filtercode, filtercode1); NodeList node = parser.extractAllNodesThatMatch(linkFilter); Node matanode = (Node) node.elementAt(0); String code = matanode.getText(); //System.out.println(code); int start = code.indexOf("charset="); code = code.substring(start); //System.out.println(code); int end = code.indexOf(" "); //System.out.println(end); if(end==-1){ end=code.length(); } String encode1 = code.substring(8, end-1); String encode2 = code.substring(9,end-1); //System.out.println(encode1+"chkc"+encode2); String[] encodes = oriEncode.split(","); if(encode1.equals(encodes[0])||encode2.equals(encodes[0])||encode1.equals(encodes[1])||encode2.equals(encodes[1])) return "utf-8"; if(encode1.equals(encodes[2])||encode2.equals(encodes[2])) return "gb2312"; if(encode1.equals(encodes[3])||encode2.equals(encodes[3])) return "gbk"; if(encode1.equals(encodes[4])||encode2.equals(encodes[4])) return "iso-8859-1"; } catch (Exception e) { }*/ return "gb2312"; }}经过爬取了上万个页面这个程序停了下来可以看到爬下来的内容我都是以网址开头空格之后就是电影的各项内容。这样爬取页面也是为了在hadoop中做数据分析。我的确做了一个数据分析电影明星哪一个成就最高,但是因为数据集的原因结果不是很理想。在之后的博客中我可能会把分析步骤发出来。1 0
- java实现简单的网络爬虫(爬取电影天堂电影信息)
- 爬取电影天堂的电影信息
- 正则爬取电影天堂电影信息
- 多线程爬虫爬取电影天堂资源
- 爬虫学习(一)---爬取电影天堂下载链接
- scrapy初步-简单静态爬虫(爬取电影天堂所有电影)
- Python爬虫实战(八):爬取电影天堂的电影下载链接
- python爬虫实现下载电影天堂电影
- scrapy实战爬取电影天堂相关信息
- java多线程-爬电影天堂上的电影下载地址
- 爬取电影天堂的所有资源到mysql
- 爬取电影天堂并存入数据库
- Python爬虫入门 | 2 爬取豆瓣电影信息
- Python抓取电影天堂电影信息
- Python—爬虫—简单爬取豆瓣电影
- 简单爬虫学习---爬取豆瓣电影top250
- 简单的爬取豆瓣电影
- 小菜鸟的第一个爬虫:豆瓣爬取电影信息
- 分页器
- Android 利用annotationProcessor生成Java代码
- 当Java的二维数组遇上clone
- React Native开发之ATOM开发实用技巧
- spring异常
- java实现简单的网络爬虫(爬取电影天堂电影信息)
- 收藏网址
- 台湾大学林轩田机器学习基石课程学习笔记4 -- Feasibility of Learning
- 欢迎使用CSDN-markdown编辑器
- JavaScript 99乘法表
- Java之【线程通信】--标志位练习
- php 利用 PHPExcel 导出 导入 Excel 方法介绍(功能介绍)
- 翻转设计模式系列——第三部分--设计模式(4)--行为型模式大比拼
- 新路程------makefile的M一定要大写。。。。