Java网络爬虫基础
Http基础
网络资源一般是Web服务器上的一些各种格式的文件,通过Http协议传输互联网上的数据.
在Java中,通常通过URL标出网络资源的位置和Web服务器建立链接,获取网页源代码.
爬虫程序通过域名服务(Domain Name Serive,简称 DNS)取得域名对应的IP地址,它首先连接到一个DNS服务器上,由DNS服务器返回域名对应的IP地址.DNS把解析到错误的域名叫做DNS劫持.
Linux常用如下命令来分析DNS解析的问题(以下命令暂以百度为例)
dig命令
$ dig www.baidu.com
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.5 <<>> www.baidu.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60412
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.baidu.com. IN A
;; ANSWER SECTION:
www.baidu.com. 419 IN CNAME www.a.shifen.com.
www.a.shifen.com. 149 IN A 110.242.68.3
www.a.shifen.com. 149 IN A 110.242.68.4
;; Query time: 1 msec
;; SERVER: 183.60.83.19#53(183.60.83.19)
;; WHEN: Wed Mar 23 22:16:36 CST 2022
;; MSG SIZE rcvd: 90
nslookup命令
$ nslookup www.baidu.com
Server: 183.60.83.19
Address: 183.60.83.19#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 110.242.68.4
Name: www.a.shifen.com
Address: 110.242.68.3
在Windows下可以以如下方法查看路由情况.
> tracert -d www.baidu.com
通过最多 30 个跃点跟踪
到 www.a.shifen.com [110.242.68.3] 的路由:
1 <1 毫秒 <1 毫秒 1 ms 192.168.1.1
2 1 ms 1 ms 1 ms 192.168.18.1
3 4 ms 3 ms 2 ms 111.161.232.1
4 3 ms 2 ms 2 ms 117.8.159.205
5 3 ms 3 ms 3 ms 117.10.223.117
6 * * * 请求超时。
7 9 ms 9 ms 9 ms 110.242.66.186
8 * * * 请求超时。
9 * * * 请求超时。
10 * * * 请求超时。
11 * * * 请求超时。
12 * * * 请求超时。
13 9 ms 9 ms 9 ms 110.242.68.3
跟踪完成。
通过Java来获取一个网站所有的IP
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args)
{
try {
List ipList = new ArrayList<>();
InetAddress[] addressesList = InetAddress.getAllByName("www.sina.com.cn");
for(InetAddress address:addressesList)
{
ipList.add(address.getHostAddress());
System.out.println(address.getHostAddress());
}
}catch (Exception e){e.printStackTrace();}
}
}
URL可选择一个指定的端口,它用于建立远程主机TCP(Transmission Control Protocol)连接的端口号,如果未指定端口则默认使用默认端口,80端口.
URI
URI包括URL和URN,但是URN并不常用.URL由3部分组成:
| https://finance.sina.com.cn/stock/ |
| 协议名 | 主机名 | 资源路径 |
| http | finance.sina.com.cn | stock |
Http规范定义了8种可能的请求方法,爬虫经常用到的有以下三种:
| 方法 | 说明 |
| GET | 检索URI种标识资源的一个简单请求 |
| HEAD | 与GET方法相同,服务器只返回状态行和头标,不返回请求文档 |
| POST | 服务器接受被写入客户端输出流中的数据的请求,可以用POST方法来提交表单参数 |
发送给Web服务器的请求头参数
| 请求头参数 | 含义 |
| Accept:text/plain,text/html | 说明了可以接收文本类型的信息 |
| Referer:https://www.sina.com.cn/ | 此值告诉服务器访问来自于哪个页面,服务器由此可以获得一些信息用于处理,有的网站会利用此参数用于防止图片盗链 |
| Keep-alive:115 | 是指在同一个链接中发出和接收多次HTTP请求 |
Web服务器处理返回的状态码分类
| 状态码 | 类型 | 作用 |
| 1xx | 信息响应类 | 表示接收到请求并且继续处理 |
| 2xx | 处理成功响应类 | 表示动作被成功接收、理解和接受 |
| 3xx | 重定向响应类 | 为了完成指定动作,必须接受进一步处理 |
| 4xx | 客户端错误 | 客户端请求包含语法错误或者不能正确执行 |
| 5xx | 服务端错误 | 服务器不能正确执行一个正确的请求 |
HTTP常用状态码
| 状态代码 | 代码描述 | 处理方式 |
| 200 | 请求成功 | 获得响应的内容,进行处理 |
| 201 | 请求完成,结果是创建了新资源.新创建资源的URI可在响应的实体中得到 | 爬虫不会遇到 |
| 202 | 请求被接受,但处理尚未完成 | 阻塞等待 |
| 204 | 服务器端已经实现了请求,但没有返回新的信息,如果客户是用户代理,则无须为此更新自身的文档视图 | 丢弃 |
| 300 | 该状态码不被HTTP/1.0的应用程序直接使用,只是作为3xx类型回应的默认解释,存在多个可用的被请求资源 | 若程序中能够处理,则进行进一步处理,如果程序中不能处理,则丢弃 |
| 301 | 请求到的资源都会分配一个永久的URL,这样就可以在将来通过该URL来访问此资源 | 重定向到分配的URL |
| 302 | 请求到的资源在一个不同的URL处临时保存 | 重定向到临时的URL |
| 304 | 请求的资源未更新 | 丢弃 |
| 400 | 非法请求 | 丢弃 |
| 401 | 未授权 | 丢弃 |
| 403 | 禁止 | 丢弃 |
| 404 | 没有找到 | 丢弃 |
| 500 | 服务器内部错误 | 丢弃 |
| 502 | 错误网关 | 丢弃 |
| 503 | 服务器暂时不可用 | 丢弃 |
Get Post Head方法的基础Java代码
Maven依赖:
org.apache.httpcomponents
httpclient
4.5.3
org.apache.httpcomponents
httpmime
4.5.3
Head:
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import java.net.URI;
public class Head {
private String url="";
public void setUrl(String url)
{
this.url=url;
}
public void doHead() throws Exception
{
CloseableHttpClient closeableHttpClient= HttpClientBuilder.create().build();
URI uri=new URI(url);
HttpHead method=new HttpHead(uri);
HttpResponse response=closeableHttpClient.execute(method);
Header[] s=response.getAllHeaders();
for(int i=0;i
Get:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Get {
private String url="";
public void setUrl(String url)
{
this.url=url;
}
private String cookie="";
public void setcookie(String cookie)
{
this.cookie=cookie;
}
private Map header=new HashMap();
public void addHeader(String key,String value)
{
header.put(key,value);
}
private String html="";
public String doGet() throws Exception
{
CloseableHttpClient closeableHttpClient= HttpClientBuilder.create().build();
HttpGet httpGet=new HttpGet(url);
// httpGet.addHeader("User-Agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36");
// httpGet.setHeader("cookie","HttpOnly; UM_distinctid=176d650b687fc-0a035a289264ec-1e2e1b0b-1fa400-176d650b688c77; Hm_lvt_080dabacb001ad3dc8b9b9049b36d43b=1609913383; f_city=%E5%A4%A9%E6%B4%A5%7C101030100%7C; Wa_lvt_1=1609913383; CNZZDATA1278536588=1934037795-1609908526-%7C1609918974");
Set> entrySet=header.entrySet();
for(Map.Entry entryset:entrySet)
{
httpGet.setHeader(entryset.getKey(),entryset.getValue());
}
HttpResponse response=closeableHttpClient.execute(httpGet);
HttpEntity entity=response.getEntity();
if(entity!=null)
{
html= EntityUtils.toString(entity,"UTF-8");
EntityUtils.consume(entity);
}
return html;
}
}
Post:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NamevaluePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNamevaluePair;
import org.apache.http.util.ByteArrayBuffer;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.*;
public class Post {
private String url="";
public void setUrl(String url)
{
this.url=url;
}
private String cookie="";
public void setcookie(String cookie)
{
this.cookie=cookie;
}
private Map header=new HashMap<>();
public void addHeader(String key,String value) {
header.put(key,value);
}
private List namevaluePairs=new ArrayList();
public void addNamevaluePairs(String key,String value)
{
namevaluePairs.add(new BasicNamevaluePair(key,value));
}
public String doPost() throws Exception
{
CloseableHttpClient httpClient= HttpClientBuilder.create().build();
HttpPost httpPost=new HttpPost(url);
Set> entrySet=header.entrySet();
for(Map.Entry entryset:entrySet)
{
httpPost.setHeader(entryset.getKey(),entryset.getValue());
}
// httpPost.setHeader("Content-Type","application/x-www-form-urlencoded");
// httpPost.setHeader("cookie",cookie);
// namevaluePairs.add(new BasicNamevaluePair("page","1"));
// namevaluePairs.add(new BasicNamevaluePair("rp","12"));
// namevaluePairs.add(new BasicNamevaluePair("sortname","_CreateTime"));
// namevaluePairs.add(new BasicNamevaluePair("sortorder","desc"));
// namevaluePairs.add(new BasicNamevaluePair("query",""));
// namevaluePairs.add(new BasicNamevaluePair("qtype",""));
// namevaluePairs.add(new BasicNamevaluePair("queryid","flowmystart"));
// namevaluePairs.add(new BasicNamevaluePair("condition","_UserName='53c6b305-5bea-450a-b7a1-11ce1feab4b2'"));
httpPost.setHeader("cookie",cookie);
httpPost.setEntity(new UrlEncodedFormEntity(namevaluePairs));
HttpResponse response=httpClient.execute(httpPost);
HttpEntity entity=response.getEntity();
InputStream inputStream=entity.getContent();
BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
ByteArrayBuffer byteArrayBuffer=new ByteArrayBuffer(20);
int current=0;
while((current=bufferedInputStream.read())!=-1)
{
byteArrayBuffer.append((byte) current);
}
String text=new String(byteArrayBuffer.toByteArray());
System.out.println(text);
return text;
}
}