保研完之后,该浪的也都浪够了,是时候重新开始认真学技术了。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
大概就是这些了。
这是我的四个类的主要作用。下面开始上代码。
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