1、全面剖析网络爬虫
你知道百度、谷歌是如何获取数以亿计的网页并且实时更新的吗?你知道在搜索领域人们常说的spider吗,本文章将介绍网络爬虫的方方面面,读完之后希望你直接能写出来一个网络爬虫,随意抓取互联网上面你感兴趣的任何东西。
既然百度、谷歌这些搜索引擎巨头已经帮我们抓取了互联网上面大部分的信息,为什么我们自己还要写爬虫呢?因为在现实生活中信息的需求是广泛的,在企业中,爬虫抓取下来的信息可以做为数据仓库多维度展示的数据源,也可以作为数据挖掘的来源,甚至有人为了炒股,抓取股票信息。既然从美国中情局到普通老百姓都需要,那还等什么,干就完了。
1.1通过指定的URL抓取网页内容
Java语言是为网络而生的编程语言,它把网络资源看成是一种文件,它对网络资源的访问和对本地文件的访问一样方便,它把请求和响应封装成流,因此我们可以根据相应内容,获得响应流,之后从流中按字节读取数据,例如,Java.net.URL有一个默认的构造函数,使用URL地址作为参数,构造URL对象。
URL pageUrl = new URL(path);
接着,可以通过获得的URL对象来取得网络流,
inputStream stream = pageUrl.openStream();
在实际项目中,网络环境比较复杂,因此,Java.net包中的api来模拟IE客户端的工作,代码量非常大,需要处理HTTP返回的状态码,设置http代理,处理HTTPS协议等工作。为了便于程序的开发,实际开发中常常使用Apache的HttpClient。
例如:
//创建一个客户端,类似于打开一个浏览器 HttpClient httpClient = new HttpClient(); //创建一个get方法,类似于浏览器中输入地址 GetMethod getMethod = new GetMethod(" //回车,获取响应代码 int statusCode = httpClient.executeMethod(getMethod); System.out.println(statusCode); //查看命中情况 System.out.println("response= " + getMethod.getResponseBodyAsString()); //释放 getMethod.releaseConnection();
在这个实例中,只是简单的返回网页内容,在现实项目中,通常需要把返回的内容写到本地文件并保存。最好还要关闭网络连接,避免资源消耗。
这个日子使用get方式来访问web资源,get请求方式把需要传递给服务器的参数作为URL的一部分传递给服务器,但是,HTTP协议本身对URL字符串长度有所限制,因此不能传递过多的参数,为了避免这个问题,可以使用HttpClient的POST方法。
//创建一个客户端,类似于打开一个浏览器 HttpClient httpClient = new HttpClient(); //创建一个post方法,类似于浏览器中输入地址 PostMethod postMethod = new PostMethod(" //使用数组传递参数 NameValuePair[] valuePairs = new NameValuePair[2]; valuePairs[0] = new NameValuePair("前段开发", "HTML"); valuePairs[1] = new NameValuePair("后端开发", "JAVA"); //设置参数 postMethod.addParameters(valuePairs); //回车,获取响应代码 int statusCode = httpClient.executeMethod(postMethod); System.out.println(statusCode); //查看命中情况 System.out.println("response= " + postMethod.getResponseBodyAsString()); System.out.println("NameValuePair[0] " + postMethod.getParameters()[0]); System.out.println("NameValuePair[1] " + postMethod.getParameters()[1]); //释放 postMethod.releaseConnection(); 结果: 200 NameValuePair[0] name=前段开发, value=HTML NameValuePair[1] name=后端开发, value=JAVA
有时,我们执行爬虫程序的机器不能直接访问WEB资源,而是需要通过代理服务器去访问,HTTPClient对代理服务器也有很好的支持。例如:
//创建HttpClient相当于打开一个代理 HttpClient httpClient = new HttpClient(); //设置代理服务器的IP和端口 httpClient.getHostConfiguration().setProxy("192.168.0.1", 8888); //告诉HttpClient,使用抢先认证,否则你会收到你没有资格的恶果 httpClient.getParams().setAuthenticationPreemptive(true); //httpClient.getParams().setParameter(CredentialsProvider.PROVIDER, new MyCredentialsProvider()); //设置代理服务器的用户名密码 httpClient.getState().setProxyCredentials(new AuthScope("192.168.0.1", AuthScope.ANY_PORT,AuthScope.ANY_REALM), new UsernamePasswordCredentials("username","Password"));
上面的例子详细解释了如何使用HTTPClient设置代理服务器,如何在局域网访问WEB资源。
1.2处理HTTP状态码
当状态码是2XX的时候,我们只需要处理200和202两种状态码,其他的可以采用简单的丢弃处理就可以解决。200的状态码标识成功,可以直接进行网页抓取,例如:
if(statsuCode == HttpStatus.SC_OK) { input = postMethod.getResponseBodyAsString(); //得到文件名 String fileName = path.substring(path.lastIndexOf('/')+1); //获取文件输出流 outPut = new FileOutputStream(fileName); //输出到文件 int tempValue = -1; while((tempValue = input.read() > 0 )){ output.write(tempValue ); } }
202的响应码,表示请求已经接受,服务器再做处理。
当返回值状态码为3XX时,通常进行转向,例如:
//处理状态为3XX的 if(statusCode==HttpStatus.SC_MOVED_TEMPORARILY|| statusCode==HttpStatus.SC_SEE_OTHER|| statusCode==HttpStatus.SC_TEMPORARY_REDIRECT){ //读取新的URL地址 Header header=getMethod.getRequestHeader("location"); if(header!=null){ String newUrl=header.getValue(); if(newUrl==null||newUrl.equals("")){ newUrl="/"; //重定向处理 GetMethod method=new GetMethod(newUrl); } } }
下面的博客地址是之前写的用Python爬虫的具体执行逻辑,内容很丰富,介绍了python爬虫主要的五个模块:
爬虫启动入口模块,
URL管理器存放已经爬虫的URL和待爬虫URL列表,
html下载器,
html解析器,
html输出器
同时可以掌握到urllib2的使用、bs4(BeautifulSoup)页面解析器、re正则表达式、urlparse、python基础知识回顾(set集合操作)等相关内容。
https://www.cnblogs.com/wenhongyu/p/7157492.html
【不是每一个问题都是钉子, 不是每一个解决方案都是锤子】
原创首发于慕课网
作者:Wenhy
来源:慕课网
共同学习,写下你的评论
评论加载中...
作者其他优质文章