爬虫是什么
爬虫又叫网络爬虫,是一种运行在互联网上为了获取数据的自动化程序。
互联网上有哪些数据值得爬取?
公司内部数据
- 业务数据,公司使用BI(Business Intelligence)、CRM系统、ERP系统、邮件系统等产生的数据;
- 财务数据,其中包括公司的支出、采购、收入等多项与公司日常运作有关的数据;
- 用户数据,无论是网站、APP还是游戏,用户注册都会填写邮箱、电话、身份证号码等数据,这些数据其实非常有价值,此外还要加上用户使用公司产品留下的行为数据。
- 历史数据,公司沉淀下来的其他各种数据。
外部数据
- 社交网站数据,包括微信、微博、人人网、Twitter、Facebook、LinkedIn等社交媒体上的数据。
说明:社交数据部分是可以爬取的,另外一部分是需要运营方授权的。 - 线下采集数据,包括Wifi热点数据、地图数据等。
说明:这一块目前做的公司比较少,但同时也比较有价值。 - 政府开放数据,包括企业征信数据、企业注册数据、法院公示数据、公共交通数据等。
说明:如果你想要找的话,可到对应政府网站下载。 - 智能设备数据,包括智能设备、传感器数据。
说明:你知道吗?一部智能手机,至少拥有8个传感设备。 - 网络爬虫数据,包括互联网上所有可以爬回的数据,文字、视频、图片其实也是数据,而且是非结构化数据。
- 企业交易数据,包括商家流水数据、支付宝交易数据、信用卡消费数据等等。
说明:目前这一部分数据是最难获取的,因为数据就是宝贵的资产。 - 企业开放数据,比如微博开放了商业数据API,腾讯开放了腾讯云分析SDK上报的应用数据,高德地图开放了LBS数据等等。
说明:如果想找更多的数据API,我推荐你去数据堂、聚合数据这两家网站上看一下,上面有大量的API接口。 - 其它数据,比如天气数据、交通数据、人口流动数据、位置数据等等。
说明:只有想不到没有弄不到。
总结
大数据即使整合完公司内部外部数据进行大数据存储,然后通过清洗,标注、去重、去噪、关联等过程可以将数据进行结构化,也可以进行大数据挖掘和数据分析,再以数据可视化呈现结果,打通数据孤岛形成数据闭环,将数据转换成“石油”和“生产资料”,最后应用到我们日常的生活、学习和工作中去。
爬虫爬取的数据有什么用
* 和搜索引擎结合使用
* 进行数据分析
对数据进行分析,提取有价值的信息(偏好、位置)
什么是数据分析?
对已经存在的数据进行归类和总结,得到有价值的信息。
- 案例说明
- Wifi 定位一个人 分析wifi周边的人流量
- 获取你的网页浏览记录 分析偏好
总结
互联网我们的爬虫不仅仅是为搜索而存在的,大多数时候是为数据分析而存在的。
爬虫开发是大数据分析的一个基本条件。
爬虫的简单分类
* 通用爬虫:百度 爬取互联网所有数据的爬虫叫做通用爬虫
* 垂直爬虫:为做数据分析而爬取特定数据的爬虫叫做垂直爬虫。
* 淘宝评论爬虫
* 淘宝商品爬虫
* 分类的标准:根据数据量或者业务范围
总结
在互联网上,大多数都是垂直爬虫,也就是值爬取一定范围内的数据。
爬虫的运行原理
你自己如何获取网页上的数据?
- 1、打开一个网页
- 2、复制 标题 新闻内容 下载图片
爬虫爬取一个页面的流程
- 3、指定一个URL
- 4、发起一个网络请求 HTTP
- 5、得到一个HTML文档
- 6、解析HTML文档
爬虫爬取多个页面
- 1、指定很多个URL
数据结构 list - 2、从list中依次拿取url
- 发起一个网络请求 HTTP
- 得到一个HTML文档
- 解析HTML文档
- 顺便解析出其他URL
- 将解析的URL存放到等待爬取的URL中
爬虫的原理图
步骤说明:
* 1、将一个种子URL存放到队里中
* 2、从队列中读取一个URL
* 3、发起网络请求(上图4-5-6步)
* 3.1、域名解析,得到IP地址
* 3.2、发起HTTP请求
* 3.3、下载页面
* 4、解析HTML文档(上图7-8-9步)
* 解析HMTL文档获取网页中所有URL
* 分页页面是否爬取过
* 如果没有爬取就放入待抓取的URL队里中
分析网络爬虫开发技术
需求:爬取一个页面的内容
* 1、人的操作:找到URL 输入到浏览器的地址栏 回车
浏览器帮我们发送了网络请求
技术实现:如何发送网络请求
* Socket(服务端、客户端)
* HttpURLConnection(用来访问http连接)
* HttpClient (操作网络请求更快的API) 学会HTTPClient
三个技术点之间的关系:
* Socket原生底层(ip、port) 除非我们自己开发游戏服务器
* HttpURLConnection JDK提供的一套访问Http资源的API
* HttpClient 基于HttpURLConnection高度封装,不需要关注网络请求的细节。
2、人的操作:得到一个HTML文档二进制数据
浏览器帮我们解析了二进制数据,将网页按照HTML的标准呈现给我们
技术实现:如何获取HTML页面
Inputstream 转化成 String 得到HTML纯文本数据。
知道HTML文档格式,因为我们要进一步解析数据3、人的操作:人为的复制、粘贴操作
通过代码来解析HTML文档,获取有用的数据。
技术实现:如何解析数据Document对象
JSOUP 为解析HTML而生。
技术点之间的关系:
Document对象是原生的API,Jsoup是更高级的框架。
总结:爬虫开发的两个核心技术
* Httpclient:帮助我们更好发送网络请求
* Jsoup:帮助我们更好的解析html。
如何模拟浏览器进行网络请求
* 1、HTTP协议
* 2、Java网络请求原生API
* 2.1、Java网络请求原生API-Get请求
* 2.2、Java网络请求原生API-Post请求
* 3、使用HttpClient进行网络请求
* 3.1、使用HttpClient进行Get请求
* 3.2、使用HttpClient进行POST请求
* 3.3、使用HttpClient进行Get请求-简单
* 3.4、使用HttpClient进行POST请求-简单
1、HTTP协议
HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。
客户端向服务器发送一个请求,请求头包含请求的方法、URL、协议版本、以及包含请求修饰符、客户信息和内容的类似于MIME的消息结构。
服务器以一个状态行作为响应,响应的内容包括消息协议的版本,成功或者错误编码加上包含服务器信息、实体元信息以及可能的实体内容。
通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个指示头域结束的空行和可选的消息体组成。
HTTP的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。
HTTP常见状态码 所有的状态码:百度百科
2、Java网络请求原生API
HttpUrlConnection
Get 方式请求网络基本流程
* 给定一个域名:www.itcast.cn
* 创建URL对象
* 通过URL对象打开一个连接
* 判断请求状态是否等于200
* 输入流:获取服务端的响应数据
* 使用BufferReader读取数据
* 关闭流
Post 方式请求网络基本流程
* 给定一个域名:www.itcast.cn
* 创建URL对象
* 通过URL对象打开一个连接
* 设定Post请求方式
* 指定 requestMethod为post
* 打开 conn.setDoOutput(true)
* 提交数据到服务器
* 获取outputStream
* 写出数据
* flush and close
* 判断请求状态是否等于200
* 输入流:获取服务端的响应数据
* 使用BufferReader读取数据
* 关闭流
2.1、Java网络请求原生API-Get请求
使用原生API发送Get请求
public class Get {
public static final String USER_AGENT = "Mozilla/5.0";
public static void main(String[] args) throws IOException {
//1、准备要访问的URL
String url = "http://www.itcast.cn";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
//2、设置Http协议的参数
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
//3、发起HTTP请求,获取状态码
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
//4、如果是正常相应,读取数据
if (responseCode == 200) {
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
}
}
2.2、Java网络请求原生API-Post请求
使用原生API发送Post请求
package cn.itcast.pcss.base.httpurlconnection;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class Post {
public static final String USER_AGENT = "Mozilla/5.0";
public static void main(String[] args) throws IOException {
String url = "http://sspc.itcast.cn/login/login.html";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", Post.USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
String urlParameters = "username=maoxiangyi&password=&maoxiangyi&reURL=http://shop.itcast.cn/item/itemList.html";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
if (responseCode == 200) {
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
}
}
}
3、使用HttpClient进行网络请求
本节介绍使用HttpClient进行网络请求。
HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
为什么有HttpClient
* 超文本传输协议(HTTP)可能是当今互联网上使用的最重要的协议
* 虽然java.net包提供了通过HTTP访问资源的基本功能,但它并没有提供许多应用程序所需的完全灵活性或功能
使用HttpClient的maven依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.2</version>
</dependency
3.1、使用HttpClient进行Get请求
使用HttpClient进行Get请求
- HttpClients.createDefault 创建一个客户端
- HttpGet 创建一个Get请求
- httpclient.execute(httpGet) 执行一个请求
- CloseableHttpResponse 获取返回值
- getStatusLine 获取状态信息
- EntityUtils 操作返回内容
代码实现
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.nio.charset.Charset;
/**
* Created by maoxiangyi on 2017/6/26.
*/
public class SimpleGet {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://sspc.itcast.cn");
CloseableHttpResponse response = httpclient.execute(httpGet);
System.out.println(response.getStatusLine());
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String html = EntityUtils.toString(entity, Charset.forName("utf-8"));
System.out.println(html);
}
response.close();
}
}
3.2、使用HttpClient进行Post请求
使用HttpClient进行Post请求
- HttpClients.createDefault 创建一个客户端
- HttpPost 创建一个Post请求
- UrlEncodedFormEntity 封装表单信息
- httpclient.execute(HttpPost) 执行一个请求
- CloseableHttpResponse 获取返回值
- getStatusLine 获取状态信息
- EntityUtils 操作返回内容
代码实现:
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* Created by maoxiangyi on 2017/6/26.
*/
public class SimplePost {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://shop.itcast.cn/login/login.html");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("username", "maoxiangyi"));
nvps.add(new BasicNameValuePair("password", "maoxiangyi"));
nvps.add(new BasicNameValuePair("reURL", "http://shop.itcast.cn/item/itemList.html"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
CloseableHttpResponse response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
//如果登录之后需要重定向,获取重定向的值
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println(header);
}
if (response.getStatusLine().getStatusCode() == 302) {
Header[] locations = response.getHeaders("Location");
String url = locations[0].getValue();
System.out.println(url);
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response1 = httpclient.execute(httpGet);
if (response1.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response1.getEntity();
String html = EntityUtils.toString(entity, Charset.forName("utf-8"));
System.out.println(html);
}
response1.close();
}
response.close();
}
}
3.3、使用HttpClient进行Get请求-简单方式
使用HttpClient进行Get请求-简单方式
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpVersion;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* Created by maoxiangyi on 2017/6/26.
*/
public class EasyGet {
public static void main(String[] args) throws IOException {
String html = Request.Get("http://shop.itcast.cn").execute().returnContent().asString(Charset.forName("UTF-8"));
System.out.println(html);
}
}
3.4、使用HttpClient进行Post请求-简单
使用HttpClient进行Post请求-简单方式
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* Created by maoxiangyi on 2017/6/26.
*/
public class EasyPost {
public static void main(String[] args) throws IOException {
HttpResponse response = Request.Post("http://shop.itcast.cn/login/login.html")
.bodyForm(Form.form().add("username", "maoxiangyi").add("password", "maoxiangyi").add("reURL","http://shop.itcast.cn/item/itemList.html").build())
.execute().returnResponse();
if (response.getStatusLine().getStatusCode() == 302) {
Header[] locations = response.getHeaders("Location");
String url = locations[0].getValue();
System.out.println(url);
HttpGet httpGet = new HttpGet(url);
String html = Request.Get(url).execute().returnContent().asString(Charset.forName("UTF-8"));
System.out.println(html);
}
}
}