网络爬虫原理详解及案例实现(一)
网络爬虫之Java实现
一、了解http协议原理
1.URI和URL
写爬虫之前我们先了解一下URI和URL,,URI的全称为 Uniform Resource Identifier,即统一资源标志符, URL 的全称为 Universal Resource Locator,即统一资源定位符。
1.举例来说 , https://www.baidu.com/favicon.ico 是Baidu 的网站图标链接,它是一个 URL,也是一个 URI,即有这样的一个图标资源,我们用 URL用RI 来唯一指定了它的访问方式,这其中包括了访问协议https、 访问路径 (/即根目录)和资源名称 favicon.ico。 通过这样一个链接,我们便可以从互联网上 找到这个资源,这就是 URL用RI。
2.URL 是 URI的子集,也就是说每个 URL 都是 URI,但不是每个 URI 都是 URL。
3.URI还包括一个子类叫作 URN,它的全称为 Universal Resource Name,即统一资 源、名称。 URN只命名资源而不指定如何定位资源。
4.URL、 URN 和 URI 关系图
5. 但是在目前的互联网中, URN 用得非常少,所以几乎所有的 URI 都是 URL, 一般的网页链接我
们既可以称为 URL, 也可以称为 URI,比较常用的称为URL。
6.URL一般由三部组成:
①协议(或称为服务方式)
②存有该资源的主机IP地址(有时也包括端口号)
③主机资源的具体地址。如目录和文件名等
2.HTTP简介
1.HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
2.HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
3.HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中。
4.HTTP协议工作于客户端——服务器端的架构之上。浏览器作为http客户端通过url向http服务端即web服务器发送请求,web服务器根据接收到的请求向客户端发送响应消息。
3.HTTP请求:Request
客户端发送一个HTTP请求到服务器的请求消息的格式:
请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。
第一部分:请求行,用来说明请求类型(方法),要访问的资源以及所使用的HTTP版本.
GET 和 POST请求方法有如下区别
- GET 请求中的参数包含在 URL 里面,数据可以在 URL 中看到,而 POST 请求的 URL 不会包 含这些数据,数据都是通过表单形式传输的,会包含在请求体中。
- GET请求提交的数据最多只有 1024 字节,而 POST方式没有限制。
第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息
- Accept:请求报头域,用于指定客户端可接受哪些类型的信息。
- Accept-Language:指定客户端可接受的语言类型。
- Accept-Encoding :指定客户端可接受的内容编码。 D Host:用于指定请求资源的主机 IP 和端口号,其内容为请求 URL 的原始服务器或网关的位 置。 从 HTTP 1. l 版本开始,请求必须包含此内容。
- Cookie :也常用复数形式 Cookies,这是网站为了辨别用户进行会话跟踪而存储在用户本地 的数据。 它的主要功能是维持当前访问会话。 例如,我们输入用户名和密码成功登录某个网 站后,服务器会用会话保存登录状态信息,后面我们每次刷新或请求该站点的其他页面时, 会发现都是登录状态,这就是 Cookies 的功劳。 Cookies 里有信息标识了我们所对应的服务器 的会话,每次浏览器在请求该站点的页面时,都会在请求头中加上 Cookies 并将其发送给服 务器,服务器通过 Cookies 识别出是我们自己,并且查出当前状态是登录状态,所以返回结 果就是登录之后才能看到的网页内容。
- User-Agent:简称 UA,它是一个特殊的字符串头,可以使服务器识别客户使用的操作系统 及版本、 浏览器及版本等信息。 在做爬虫时加上此信息,可以伪装为浏览器;如果不加,很 可能会被识别州为爬虫。
- Content-Type:也叫互联网媒体类型( Internet Media Type )或者 MIME 类型,在 HTTP 协议 消息头中,它用来表示具体请求中的媒体类型信息。 例如, text/html 代表 HTML 格式, image/gif代表 GIF 图片, application/json 代表 JSON类型
第三部分:空行,请求头部后面的空行是必须的
第四部分:请求数据也叫主体(请求体),可以添加任意的其他数据。
请求体一般承载的内容是 POST请求中的表单数据,而对于 GET请求,请求体则为空。
4.HTTP响应
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
第一部分:状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。
第二部分:消息报头(响应头),用来说明客户端要使用的一些附加信息
响应头包含了服务器对请求的应答信息,如 Content-Type、 Server、 Set-Cookie 等。 下面简要说明 一些常用的头信息。
- Date: 标识响应产生的时间。
- Last-Modified : 指定资源的最后修改时间。
- Content-Encoding : 指定响应内容的编码。
- Server: 包含服务器的信息 ,比如名称、版本号等。
- Content-Type: 文档类型,指定返回的数据类型是什么 ,如 text/html 代表返回 HTML 文档, application/x-javascript !J!U代表返回 JavaScript 文件, image/jpeg 则代表返回图片。
- Set-Cookie : 设置 Cookies。 响应头中的 Set-Cookie 告诉浏览器需要将此内容放在 Cookies 中 , 下次请求携带 Cookies 请求。
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文(响应体),服务器返回给客户端的文本信息。
响应的正文数据都在响应体中,比如请求网页时,它的响应体就 是网页的 HTML 代码; 请求一张图片时, 它的响应体就是图片的二进制数据。 我们做爬虫请求网页后, 要解析的内容就是响应体
5.HTTP工作原理
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
以下是 HTTP 请求/响应的步骤:
1、客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。
2、发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
3、服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4、释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5、客户端浏览器解析HTML内容
- 利用Java net包下的URLConnection,辅以io流相关知识获取网页源码
public class SpiderDemo1 {
public static void main(String[] args) throws Exception {
// TODO 自动生成的方法存根
String result="";
BufferedReader br=null;
try{
URL url=new URL("http://www.baidu.com");
URLConnection connection=url.openConnection();
/*当我们拿到一个URLConnection对象后,并不代表客户端已经和服务器建立了连接。只有主动调用其connect()方法才去和服务器建立连接。
不过当我们调用getInputStream(),getContent(),getHeaderField()和其他要求打开连接的方法时,如果连接尚未打开,它们就会调用connect()。
所以,在实际开发中我们主动调用connect()方法的机会很少。*/
connection.connect();
InputStream input=connection.getInputStream();
br=new BufferedReader(new InputStreamReader(input,"utf-8"));
String line="";
while((line=br.readLine())!=null){
result+=line;
}
}catch(Exception e){
e.printStackTrace();
}
// 使用finally来关闭输入流
finally {
try {
if (br != null) {
br.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
System.out.println(result);
}
}
- 利用HTTPClient结合JSoup抓取和解析网页的简单案例
public class WebData {
public static void main(String[] args) throws Exception{
//创建httpclient对象,即创建了一个浏览器
HttpClient hClient=new DefaultHttpClient();
//设置响应时间,传输源码时间,以及设置代理服务器
/*hClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
.setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000)
.setParameter(ConnRouteParams.DEFAULT_PROXY,new HttpHost("140.143.246.163",8080));*/
//创建一个get类型的http请求对象
HttpGet hget=new HttpGet("https://123.sogou.com/");
//添加请求头信息
hget.addHeader("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Mobile Safari/537.36");
hget.addHeader("Connection","keep-alive");
//向网站发送请求获取网页源码
String content="";
try{
//浏览器发送请求,获得服务器的响应
HttpResponse responce=hClient.execute(hget);
//获得响应主体的字符串形式
content=EntityUtils.toString(responce.getEntity(),"utf-8");
}catch(Exception e){
e.printStackTrace();
}
hget.releaseConnection();
//使用JSoup解析网页源码
Document doc=Jsoup.parse(content);
String urlString="";
Elements elements=doc.select("div.m-nav a");
//System.out.println(element.text());
for(Element e:elements){
urlString=e.text()+":"+e.attr("href");
System.out.println(urlString);
}
}
}