谷歌学术搜索 简易PDF爬虫

谷歌学术搜索 简易PDF爬虫保研完之后,该浪的也都浪够了,是时候重新开始认真学技术了。2015年12月20号,我被分配到一个浙大的项目中去,去了之后我发现什么都不会,而且这个项目中好多浙大的研究生,博士。我有点方,不过项目总负责人王老师倒来了个积极,在一一向这些学神们介绍了我之后,我不觉感到肩上的担子重了。不过我有信心,同样都是人,我努力也一定能和他们一样的(更何况我一直认为自己不一般,只是没到时候,嘿嘿)。——

    保研完之后,该浪的也都浪够了,是时候重新开始认真学技术了。2015年12月20号,我被分配到一个浙大的项目中去,去了之后我发现什么都不会,而且这个项目中好多浙大的研究生,博士。我有点方,不过项目总负责人王老师倒来了个积极,在一一向这些学神们介绍了我之后,我不觉感到肩上的担子重了。不过我有信心,同样都是人,我努力也一定能和他们一样的(更何况我一直认为自己不一般,只是没到时候,嘿嘿)。


———————————————————————————————————————————————————


    刚接触这个项目的时候,因为什么都不会,所以学长给我讲述了这个项目怎么怎么需要论文数据之后,就分配给了我整理数据的工作(一开始听到确实让人感觉很低级…)。一开始先要学会搜集数据,所以我就开始了爬虫的学习,之前虽然接触过,但从来没有自己打过爬虫程序,反正是学习为主,所以我就决定自己去学习爬虫技巧,本次带来的就是我自己编的一个谷歌学术搜索的爬虫,它会自动下载谷歌学术上面的PDF。


    我开发环境是Eclipse,开发语言是java。还要配合数据库存储对应数据。在开始编程之前,先介绍一下我用的几个jar包:

    1.commons-httpclient-3.1.jar

    2.htmlparser1_6.jar

    3.mysql-connector-java-commercial-5.1.25-bin.jar

    4.commons-io-2.4.jar

    大概就是这些了。


谷歌学术搜索 简易PDF爬虫

这是我的四个类的主要作用。下面开始上代码。

MainProcess类:

package com.google.search;



import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class MainProcess {
	static String st="http://scholar.google.com/scholar?start=0&q=graphic+fluid&hl=zh-CN&as_sdt=0,5";
	static String name="GoogleDownload";
	static int num=10;
  public static void main(String Args[])throws Exception{

	Connection conn=null;
	
	//connect the MySQL database
	try {
		Class.forName("com.mysql.jdbc.Driver");
		String dburl = "jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf8";
		conn = DriverManager.getConnection(dburl, "root", "");
		System.out.println("connection built");
	} catch (SQLException e) {
		e.printStackTrace();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}
	
	//If you need...
	//InputSystem();

	CreatTable(conn);
	FileCatch ft=new FileCatch();
	ft.start(st,num,conn);
	
	DlProcess(conn);
	conn.close();
	System.out.println("Done");
  }
  public static void InputSystem(){
	Scanner sc=new Scanner(System.in);
	
	System.out.println("Which file would you want to search?");
	st=sc.next();
	System.out.println("How many files would you want to search?");
	num=sc.nextInt();
	System.out.println("What's your Database's name?");
	name=sc.next();
	System.out.println(st+" "+num+" "+name);
  }
  public static void CreatTable(Connection conn)throws Exception{

	String sql=null;
	Statement stat=null;
	ResultSet rs=null;
	
	try{
	sql="create database if not exists "+name;
	stat=conn.createStatement();
	stat.executeUpdate(sql);
	
	sql = "USE "+name;
	stat = conn.createStatement();
	stat.executeUpdate(sql);
	
	sql="create table if not exists URL (recordID int(5) not null auto_increment, URL text not null, primary key (recordID)) engine=InnoDB DEFAULT CHARSET=utf8";
	stat=conn.createStatement();
	stat.executeUpdate(sql);
	}catch (SQLException e) {
		e.printStackTrace();
	}
	
  }
  public static void DlProcess(Connection conn)throws Exception{
		String sql=null;
		Statement stat=null;
		ResultSet rs=null;
		Scanner sc=new Scanner(System.in);
		int num=0,num2;
		
		sql = "SELECT count(*) FROM url";
		stat = conn.createStatement();
		rs = stat.executeQuery(sql);
		if(rs.next()) num=rs.getInt(1);
		System.out.println("There are "+num+" url records finded. How much will you want to download?");
        num2=sc.nextInt();
        if(num2>num) num2=num;
        PaperDownload pd=new PaperDownload();
        pd.start(conn,num2);
  }
}

FileCatch类:

package com.google.search;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;

public class FileCatch {
  public static void start(String path,int num,Connection conn)throws Exception{
	int i;
	FileParse fp=new FileParse();
	for(i=1;i<=num;i++){
		HttpClient httpclient=new HttpClient();
		InputStream in=null;
		OutputStream out=null;
		
		GetMethod getMethod = new GetMethod(path);
		System.out.println("Ping...");
		setHeaders(getMethod);
		int statusCode = httpclient.executeMethod(getMethod);
		
		if (statusCode == HttpStatus.SC_OK){
		  System.out.println("Ping is OK!");
		  in=getMethod.getResponseBodyAsStream();
		  String fname="cache.txt";
		  out=new FileOutputStream(fname);
		  int tempByte=-1;
		  while ((tempByte = in.read()) > 0) {
			    out.write(tempByte);
		  }
		  in.close();
		  out.close();
		  
		}
		fp.start(conn);
		System.out.println("One page clear!");
		path=exchange(path);
	}
	i--;
    System.out.println("Sum up to "+i+" pages catched.");
  }
  private static void setHeaders(GetMethod method) { 
		    method.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;"); 
		    method.setRequestHeader("Accept-Language", "zh-cn"); 
		    method.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3"); 
		    method.setRequestHeader("Accept-Charset", "gb2312"); 
		    method.setRequestHeader("Keep-Alive", "300"); 
		    method.setRequestHeader("Connection", "Keep-Alive"); 
		    method.setRequestHeader("Cache-Control", "no-cache"); 
  } 
	private static String exchange(String path){
		  String ne="",t1,t2;
		  int l=path.length(),x,num;
		  t1=path.substring(0,40);

		  x=path.indexOf("&");
	      num=Integer.parseInt(path.substring(40,x));
	      num+=10;
	      ne=t1+num+path.substring(x,l);
		  return ne;
	    }
}

FileParse类:

package com.google.search;

import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
import java.util.ArrayList;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.BufferedReader;

import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

public class FileParse{
  
  public static void start(Connection conn)throws Exception{

    Parser parser= new Parser(openFile("cache.txt"));
	HasAttributeFilter filter = new HasAttributeFilter("href"); 
	
	try {
		NodeList list = parser.parse(filter);
		int count = list.size();
		
		//process every link on this page
		for(int i=0; i<count; i++) {
			Node node = list.elementAt(i);
			
			if(node instanceof LinkTag) {
				LinkTag link = (LinkTag) node;
				String nextlink = link.extractLink();
				String mainurl = ".pdf";

				if(nextlink.endsWith(mainurl)) {
					String sql = null;
					ResultSet rs = null;
					PreparedStatement pstmt = null;
					Statement stmt = null;
					String tag = null;
					
					//do not save any page from "wp-content"
					/*if(nextlink.startsWith(wpurl) ||  suffix(nextlink)) {
						continue;
					}*/
					
					try {
						//check if the link already exists in the database
						sql = "SELECT * FROM url WHERE URL = '" + nextlink + "'";
						stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE);
						rs = stmt.executeQuery(sql);
						if(rs.next()) continue;
			            	
			            	sql = "INSERT INTO url (URL) VALUES ('" + nextlink + "')";
			            	pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
			            	pstmt.execute();
			            	System.out.println(nextlink);
			         
					} catch (SQLException e) {
						//handle the exceptions
						System.out.println("SQLException: " + e.getMessage());
					    System.out.println("SQLState: " + e.getSQLState());
					    System.out.println("VendorError: " + e.getErrorCode());
					} finally {
						//close and release the resources of PreparedStatement, ResultSet and Statement
						if(pstmt != null) {
							try {
								pstmt.close();
							} catch (SQLException e2) {}
						}
						pstmt = null;
						
						if(rs != null) {
							try {
								rs.close();
							} catch (SQLException e1) {}
						}
						rs = null;
						
						if(stmt != null) {
							try {
								stmt.close();
							} catch (SQLException e3) {}
						}
						stmt = null;
					}
					
				}
			}
		}
	} catch (ParserException e) {
		e.printStackTrace();
	}
  }
  public static String openFile( String szFileName ) {
      try {
          BufferedReader bis = new BufferedReader(new InputStreamReader(new FileInputStream( new File(szFileName)),"gb2312") );
          String szContent="";
          String szTemp;
          
          while ( (szTemp = bis.readLine()) != null) {
              szContent+=szTemp+"\n";
          }
          bis.close();
          return szContent;
      }
      catch( Exception e ) {
          return "";
      }
  }

}

PaperDownload类:

package com.google.search;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.commons.io.FileUtils;
 


public class PaperDownload {
  public static void start(Connection conn,int num)throws Exception{
		String sql=null;
		Statement stat=null;
		ResultSet rs=null;
		String st="";
		int i=0;
		
		sql = "SELECT * FROM url";
		stat = conn.createStatement();
		rs = stat.executeQuery(sql);
		
		while(rs.next()){
		  st=rs.getNString(2);
		  i++;
		  if(i>num) break;
		  downloadAndSave(st,"D:\\Eclipse文件\\GoogleScholarSpider\\Paper\\file"+i+".pdf");
		}
		System.out.println("There are "+num+" papers downloaded successfully!");
  }
	 public static void downloadAndSave(String source, String destination) {  
	        try {  
	            URL url = new URL(source);  
	             File file = new File(destination);   
	             System.out.println(88);
	             FileUtils.copyURLToFile(url, file);  
	            System.out.println(source + "下载完成");  
	         } catch (MalformedURLException e) {  
	             System.out.println("URL格式出错,请检查");  
	            e.printStackTrace();  
	        } catch (IOException e) {  
	             System.out.println("I/O 错误");  
	             e.printStackTrace();  
	        }  
	     }  
}

下面我来慢慢讲我这个程序的运行原理:


       首先程序是由MainProcess中的main开始的,一开始的连接数据库,之后这个conn会贯穿程序的始终。接下来有几个重要的值,如果你希望是程序运行的时候输入的,可以把InputSystem重新加进程序里。它们自己也有默认值。在配置好这些重要的值之后,就开始了页面的抓取,我们进入了FileCatch当中去。想要获得页面的内容,必须先获得该页面的响应,这里我用的是HttpClient+GetMethod。不过事实上这么做只能获取一般页面的响应,这是因为某些网站的页面有保护措施,过滤掉了一些没用的请求。所以我们要借助这里给出的setHeaders方法。这样网站就会认为是浏览器在请求页面的响应,这样就能获得大部分页面的响应了(有些时候谷歌学术就是ping不通,这个时候你就需要神奇的VPN)。在成功获得页面的响应之后,即statusCode == HttpStatus.SC_OK,就可以开始获取页面的内容了,这里用的是in=getMethod.getResponseBodyAsStream(); 获得页面响应的输出流。我先把它读到了一个文件中去。保存好这个页面之后,接下来就是FileParse的工作了。不过FileCatch还没用完,因为在谷歌学术上搜索,你不可能只盯着一个页面看。所以我这里设置了自动换页系统,这个系统说来也简单,就是抓住了谷歌页面地址的规律,所以就不多说了。在FileParse中,

        Parser parser= new Parser(openFile(“cache.txt”));
HasAttributeFilter filter = new HasAttributeFilter(“href”); 

         这两个是很重要的类,Parser就是一个爬虫类,它会根据HasAttributeFilter中给出的关键词,通过NodeList list = parser.parse(filter); 直接就在NodeList中得到全部的href链接,之后我们过滤出结尾是pdf的链接。将这些url数据全部存储到数据库中,这就是FileParse的工作。

        接下来我们回到MainProcess中来,我们还有最后一个类,即PaperDownload类,它的工作顾名思义即对存储在数据库中的url进行一一下载。所用的方法主要是org.apache.commons.io.FileUtils中的FileUtils.copyURLToFile,简单暴力,其他细节就不多说了。


        当然我这个爬虫只是一个简单的教学级爬虫,许多地方都存在着不足,希望读者能够自己查阅更多的资料来完善。


今天的文章谷歌学术搜索 简易PDF爬虫分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/11635.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注