Java网络爬虫基础
Http基础
网络资源一般是Web服务器上的一些各种格式的文件,通过Http协议传输互联网上的数据.
在Java中,通常通过URL标出网络资源的位置和Web服务器建立链接,获取网页源代码.
爬虫程序通过域名服务(Domain Name Serive,简称 DNS)取得域名对应的IP地址,它首先连接到一个DNS服务器上,由DNS服务器返回域名对应的IP地址.DNS把解析到错误的域名叫做DNS劫持.
Linux常用如下命令来分析DNS解析的问题(以下命令暂以百度为例)
$ 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 www.baidu.comServer: 183.60.83.19
Address: 183.60.83.19#53Non-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.12 1 ms 1 ms 1 ms 192.168.18.13 4 ms 3 ms 2 ms 111.161.232.14 3 ms 2 ms 2 ms 117.8.159.2055 3 ms 3 ms 3 ms 117.10.223.1176 * * * 请求超时。7 9 ms 9 ms 9 ms 110.242.66.1868 * * * 请求超时。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<String> 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依赖:
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.3</version>
</dependency>
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<s.length;i++){Header hd=s[i];System.out.println("Header Name: "+hd.getName()+" "+"Header Value: "+hd.getValue());}}
}
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<Map.Entry<String,String>> entrySet=header.entrySet();for(Map.Entry<String,String> 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<String,String> header=new HashMap<>();public void addHeader(String key,String value) {header.put(key,value);}private List<NameValuePair> nameValuePairs=new ArrayList<NameValuePair>();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<Map.Entry<String,String>> entrySet=header.entrySet();for(Map.Entry<String,String> 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;}
}