目录
[1. 客户端(你)](#1. 客户端(你))
[2. 服务器(餐厅)](#2. 服务器(餐厅))
[3. 请求(点餐)](#3. 请求(点餐))
[4. 响应(上菜)](#4. 响应(上菜))
[5. 状态码(上菜情况反馈)](#5. 状态码(上菜情况反馈))
[使用 Python 的 requests 库发起请求](#使用 Python 的 requests 库发起请求)
[1. 安装 requests 库](#1. 安装 requests 库)
[2. 导入 requests 库](#2. 导入 requests 库)
[3. 确定请求的 URL](#3. 确定请求的 URL)
[4. 选择请求方法](#4. 选择请求方法)
[GET 请求](#GET 请求)
[POST 请求](#POST 请求)
[5. 处理请求头(可选)](#5. 处理请求头(可选))
[6. 处理响应](#6. 处理响应)
[JavaScript(使用 fetch API)](#JavaScript(使用 fetch API))
[Java(使用 HttpURLConnection)](#Java(使用 HttpURLConnection))
[查询参数(Query Parameters)](#查询参数(Query Parameters))
[请求体参数(Body Parameters)](#请求体参数(Body Parameters))
[请求头参数(Header Parameters)](#请求头参数(Header Parameters))
[1. 确定需求](#1. 确定需求)
[2. 构建请求](#2. 构建请求)
[3. 发送请求](#3. 发送请求)
[4. 解析数据(处理)](#4. 解析数据(处理))
[5. 存储数据](#5. 存储数据)
什么是爬虫?
具体学习之前先了解一些理论上的知识。
爬虫,也被称为网络爬虫(Web Crawler)、网络蜘蛛(Web Spider)或机器人(Bot),是一种按照一定规则,自动地抓取万维网信息的程序或者脚本。
爬虫的工作原理
++发起请求++ :爬虫程序通过 HTTP 协议,向目标网站的服务器发送请求,请求内容可以是网页、图片、文件等。常见的请求方法有 GET(用于获取资源)和 POST(用于向服务器提交数据)。
++获取响应内容++ :服务器接收到请求后,会根据请求的内容进行处理,并返回响应。响应内容可以是 HTML 页面、JSON 数据、图片等。
++解析内容++ :爬虫程序需要对获取到的响应内容进行解析,提取出需要的信息。对于 HTML 页面,可以使用 BeautifulSoup、lxml 等库进行解析;对于 JSON 数据,可以使用 Python 的 json 模块进行解析。
++保存数据++:将解析后的数据保存到本地文件(如 CSV、JSON、Excel 等)或数据库(如 MySQL、MongoDB 等)中,以便后续的分析和使用。
爬虫的应用场景
++搜索引擎++ :百度、谷歌等搜索引擎通过爬虫程序抓取互联网上的网页,建立索引,以便用户可以快速地搜索到相关信息。
++数据采集++ :企业或个人可以使用爬虫程序采集行业数据、市场信息、竞争对手数据等,为决策提供支持。
++新闻聚合:++ 一些新闻网站会使用爬虫程序抓取各大新闻网站的新闻,聚合到自己的网站上,为用户提供一站式的新闻服务。
++价格监控++:电商平台或消费者可以使用爬虫程序监控商品价格的变化,及时发现价格波动,以便做出购买决策。
爬虫的分类
++通用爬虫++ :通用爬虫是最常见的爬虫类型,它会遍历整个互联网,抓取各种类型的网页。搜索引擎的爬虫就是典型的通用爬虫。
++聚焦爬虫:++ 聚焦爬虫是针对特定主题或领域的网页进行抓取的爬虫。例如,只抓取科技新闻、电商商品信息等。
++增量式爬虫++ :增量式爬虫只抓取那些在上次抓取后发生变化的网页,避免重复抓取,提高效率。
++深层爬虫++:深层爬虫会深入到网页中的链接,抓取更多层次的网页信息。
网络请求
爬虫其实是一个很庞大的课题,涉及的内容其实非常多。这篇文章主要讲解爬虫的核心内容之一的网络请求。
怎么理解网络请求?
我们可以把网络请求想象成一次去餐厅点餐的过程。在这个类比中,各个角色和步骤对应如下:
1. 客户端(你)
你就相当于运行爬虫程序的客户端。你想去餐厅吃东西,就像爬虫程序要从网站获取数据一样,你有获取食物(数据)的需求。
2. 服务器(餐厅)
餐厅就是服务器,它有各种各样的菜品(数据)可供提供。餐厅会根据顾客(客户端)的要求来准备食物(处理请求并返回数据)。
3. 请求(点餐)
当你进入餐厅后,你会向服务员(HTTP 协议)说明你想要点的菜(请求的资源),这就相当于爬虫程序向服务器发送请求。请求中会包含你想要的具体内容,比如你要点的是汉堡、薯条还是饮料,对应到网络请求中就是你要访问的网页地址、请求的参数等。
4. 响应(上菜)
服务员听到你的点餐要求后,会把信息传达给厨房(服务器的处理程序),厨房根据你的要求准备食物(处理请求),然后服务员把做好的食物(响应数据)端给你。在网络请求中,服务器处理完请求后,会把响应数据(如 HTML 页面、JSON 数据等)返回给客户端。
5. 状态码(上菜情况反馈)
餐厅服务员上菜的时候可能会告诉你一些情况,比如菜没了(缺货)或者很快就好(正在准备)。在网络请求中,服务器会返回一个状态码来告知请求的处理结果,例如 200 表示请求成功,404 表示请求的资源不存在,500 表示服务器内部错误等。
+----------------+ +----------------+
| 客户端(你) | -- 请求 --> | 服务器(餐厅) |
| (运行爬虫程序) | | (存储数据的网站) |
+----------------+ +----------------+
| |
| <-- 响应(数据) ---- |
| |
+----------------+ +----------------+
| 解析和处理数据 | | 处理请求逻辑 |
| (分析和提取数据)| | (准备数据) |
+----------------+ +----------------+
发起请求的步骤
发起网络请求是爬虫程序获取数据的关键步骤,以下以 Python 语言为例,结合常见的 requests
库,详细介绍发起请求的一般步骤,同时也会简单提及其他语言和工具的使用方法。
使用 Python 的 requests
库发起请求
1. 安装 requests
库
确保自己已经下载了python。如果你还没有安装 requests
库,可以WIN+R在系统里使用以下命令进行安装:
pip install requests
2. 导入 requests
库
在 Python 代码中,首先需要导入 requests
库,以便后续使用其提供的功能。
import requests
3. 确定请求的 URL
URL(统一资源定位符)是网络上资源的地址,就像你要去的餐厅的地址一样。你需要明确要请求的网页或资源的 URL。
url = 'https://www.example.com'
4. 选择请求方法
常见的 HTTP 请求方法有 GET、POST、PUT、DELETE 等,其中 GET 用于获取资源,POST 用于向服务器提交数据。
GET 请求
# 发起 GET 请求
response = requests.get(url)
POST 请求
如果需要在请求中传递数据(如表单数据),可以使用 POST 请求。
# 定义要提交的数据
data = {
'username': 'example_user',
'password': 'example_password'
}
# 发起 POST 请求
response = requests.post(url, data=data)
5. 处理请求头(可选)
有些网站会对请求进行验证,要求请求头中包含特定的信息,如 User-Agent
(用于模拟浏览器类型)、Cookie
等。可以通过设置请求头来满足这些要求。
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
response = requests.get(url, headers=headers)
6. 处理响应
请求发送后,服务器会返回一个响应对象,你可以通过该对象获取响应的状态码、内容等信息。
# 检查响应状态码
if response.status_code == 200:
print("请求成功!")
# 获取响应内容
content = response.text
print(content)
else:
print(f"请求失败,状态码: {response.status_code}")
使用其他语言和工具发起请求
JavaScript(使用 fetch
API)
const url = 'https://www.example.com';
fetch(url)
.then(response => {
if (response.ok) {
return response.text();
}
throw new Error('请求失败');
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error(error);
});
Java(使用 HttpURLConnection
)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpRequestExample {
public static void main(String[] args) {
try {
URL url = new URL("https://www.example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println(response.toString());
} else {
System.out.println("请求失败,状态码: " + responseCode);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上就是发起网络请求的一般步骤,不同的语言和工具在具体实现上可能会有所不同,但基本的思路是相似的。
响应成功
定义
当服务器成功处理了爬虫所发起的请求,并返回了所需的数据,就意味着响应成功。一般来说,HTTP 状态码处于 200 - 299 区间都代表请求成功被服务器接收、理解并处理。
常见状态码及含义
- 200 OK:这是最常见的成功状态码。它表明服务器已经成功处理了请求,并且返回了请求的资源。例如,当你使用爬虫请求一个网页时,服务器返回 200 状态码,就意味着你可以正常获取到该网页的 HTML 内容。
- 201 Created:表示请求已经成功,并且在服务器上创建了新的资源。通常在向服务器提交数据以创建新记录(如创建一个新用户、新文章等)时会返回此状态码。不过在普通网页爬虫场景中相对少见。
- 204 No Content:服务器成功处理了请求,但没有返回任何内容。常用于执行一些操作但不需要返回数据的情况,例如删除操作,服务器处理成功后可能返回 204 状态码。
处理流程
当爬虫接收到成功响应后,通常会进行以下操作:
- 解析响应内容:如果返回的是 HTML 页面,爬虫会使用解析库(如 BeautifulSoup、lxml 等)提取所需的数据;如果是 JSON 格式的数据,则会将其转换为 Python 字典或列表来处理。
- 数据存储:将提取到的有效数据存储到本地文件(如 CSV、JSON 文件)或数据库(如 MySQL、MongoDB 等)中,以便后续分析和使用。
响应失败
定义
响应失败指的是服务器未能成功处理请求,或者在请求过程中出现了各种问题,导致无法获取到所需的数据。不同的 HTTP 状态码代表了不同类型的失败原因。
常见状态码及含义
- 4xx 客户端错误
- 400 Bad Request:表示客户端发送的请求有语法错误,不能被服务器所识别。可能是请求参数格式错误、请求头信息不完整等原因导致。
- 401 Unauthorized:请求需要用户进行身份验证,但客户端没有提供有效的身份凭证。比如访问需要登录的网站,未提供正确的用户名和密码时可能会返回此状态码。
- 403 Forbidden:服务器理解请求客户端的请求,但是拒绝执行此请求。这可能是因为服务器配置了访问限制,禁止爬虫访问该资源,或者 IP 被封禁等原因。
- 404 Not Found:请求的资源不存在。可能是 URL 拼写错误,或者该资源已经被删除。
- 5xx 服务器错误
- 500 Internal Server Error:服务器内部错误,无法完成请求。这通常是服务器端代码出现了 bug 或者服务器资源耗尽等原因导致。
- 502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。可能是上游服务器出现故障或者网络连接问题。
- 503 Service Unavailable:服务器暂时处于超负载或正在进行维护,无法处理请求。通常服务器会在响应头中包含一个 Retry - After 字段,指示客户端在多长时间后可以再次尝试请求。
处理流程
当爬虫遇到响应失败时,一般会采取以下措施:
- 重试机制:对于一些可能是临时网络问题导致的失败(如 503 状态码),可以设置重试次数和重试间隔时间,多次尝试重新发送请求。
- 错误记录:记录失败的请求信息,包括 URL、状态码、错误信息等,以便后续分析问题和调试。
- 调整策略:如果是因为 IP 被封禁导致 403 状态码,可以考虑使用代理 IP 来更换请求的 IP 地址;如果是请求参数错误,需要检查并修正请求参数。
响应失败大部分时候是身份原因,服务器发现我的客户并不是浏览器,这个时候可以在请求参数中携带一个浏览器的身份信息。
什么是请求参数
在网络请求中,请求参数是客户端(如爬虫程序)向服务器发送请求时附带的额外信息,服务器会根据这些参数来生成不同的响应结果。请求参数可以分为以下几种常见类型,且会根据不同的HTTP请求方法,以不同的形式进行传递。
请求参数的类型
查询参数(Query Parameters)
- 定义 :查询参数通常用于 GET 请求,它会附加在 URL 的末尾,以键值对的形式存在,多个参数之间用
&
符号分隔,参数与 URL 之间用?
符号分隔。 - 示例 :当你在搜索引擎中搜索关键词时,URL 中就会包含查询参数。例如,在百度搜索 "苹果",URL 可能是
https://www.baidu.com/s?wd=苹果
,其中wd
是参数名,苹果
是参数值。在爬虫中,如果要请求这个页面,可以构造包含该查询参数的 URL 进行请求。
请求体参数(Body Parameters)
- 定义:请求体参数常用于 POST、PUT 等请求方法,它是请求消息体中的数据。请求体可以包含多种格式的数据,如表单数据、JSON 数据、XML 数据等。
- 示例
-
表单数据 :当你在网页上填写表单并提交时,表单数据会作为请求体参数发送到服务器。例如,一个简单的登录表单,包含用户名和密码,使用 Python 的
requests
库发送 POST 请求时,可以这样构造表单数据:import requests
data = {
'username': 'example_user',
'password': 'example_password'
}
response = requests.post('https://example.com/login', data=data)- JSON 数据:在前后端分离的开发中,很多接口接收和返回的是 JSON 格式的数据。使用
requests
库发送包含 JSON 数据的请求示例如下:
import requests
import jsondata = {
'name': 'John',
'age': 30
}
headers = {'Content-Type': 'application/json'}
response = requests.post('https://example.com/api/user', data=json.dumps(data), headers=headers) - JSON 数据:在前后端分离的开发中,很多接口接收和返回的是 JSON 格式的数据。使用
-
请求头参数(Header Parameters)
- 定义:请求头参数是包含在 HTTP 请求头中的信息,用于传递一些关于请求的额外元数据,如用户代理、授权信息、缓存控制等。服务器可以根据这些信息来做出不同的响应。
- 示例
-
User - Agent:用于标识客户端的类型和版本。有些网站会根据 User - Agent 来判断请求是来自浏览器还是爬虫,如果检测到是爬虫可能会进行限制。因此,在爬虫中通常需要设置一个合适的 User - Agent 来模拟浏览器请求。
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
response = requests.get('https://example.com', headers=headers)- Authorization:用于传递身份验证信息,如访问需要授权的 API 时,需要在请求头中包含有效的授权令牌。
import requests
headers = {
'Authorization': 'Bearer your_access_token'
}
response = requests.get('https://example.com/api/protected', headers=headers)
-
示例仅供参考。
如何进行爬虫?
1. 确定需求
明确自己进行爬虫的目标,这是整个爬虫项目的基础。
- 明确要爬取的网站:确定具体的目标网站,比如你想获取科技新闻,可能选择 36氪、虎嗅网等;若想抓取商品信息,可选择淘宝、京东等电商平台。
- 明确要获取的数据:详细规划需要从网页中提取的数据项。例如在新闻网站,可能需要文章标题、发布时间、作者、正文内容、标签等;在电商网站,可能关注商品名称、价格、销量、评价等。
2. 构建请求
根据确定的需求,构建合适的HTTP请求。
-
选择请求方法:常见的请求方法有GET和POST。GET方法用于从服务器获取资源,当访问网页时通常使用GET请求;POST方法用于向服务器提交数据,比如登录表单提交、搜索请求等。
-
设置请求头:为了模拟浏览器行为,避免被网站的反爬机制拦截,需要设置合适的请求头。其中User - Agent是比较重要的请求头字段,用于标识客户端的类型和版本。示例代码如下:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
url = 'https://example.com'
response = requests.get(url, headers=headers) -
处理请求参数:如果请求需要携带参数,如查询参数或表单数据,需要正确设置。对于GET请求,参数通常附加在URL后面;对于POST请求,参数通常放在请求体中。示例代码如下:
GET请求带参数
params = {
'keyword': 'python',
'page': 1
}
response = requests.get('https://example.com/search', params=params, headers=headers)POST请求带参数
data = {
'username': 'testuser',
'password': 'testpassword'
}
response = requests.post('https://example.com/login', data=data, headers=headers)
3. 发送请求
使用HTTP请求库向目标网站发送请求,获取响应内容。在Python中,requests
库是一个常用的HTTP请求库。示例代码如下:
import requests
url = 'https://example.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status() # 检查请求是否成功
except requests.RequestException as e:
print(f"请求出错: {e}")
4. 解析数据(处理)
1)JSON内容
如果服务器返回的是JSON格式的数据,可以使用Python的json
模块进行解析。示例代码如下:
import requests
import json
url = 'https://example.com/api/data'
response = requests.get(url)
if response.status_code == 200:
try:
data = response.json() # 将响应内容解析为JSON对象
# 处理JSON数据
for item in data:
print(item['name'])
except json.JSONDecodeError as e:
print(f"JSON解析出错: {e}")
2)HTML内容、文本内容
对于HTML内容,可以使用BeautifulSoup
或lxml
等库进行解析。示例代码如下:
from bs4 import BeautifulSoup
import requests
url = 'https://example.com'
response = requests.get(url)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# 提取标题
title = soup.find('title').text
print(title)
# 提取所有链接
links = soup.find_all('a')
for link in links:
print(link.get('href'))
5. 存储数据
将解析后的数据存储到合适的存储介质中。
文件存储
-
CSV文件:适合存储结构化的数据,如表格数据。示例代码如下:
import csv
data = [
{'name': 'John', 'age': 30},
{'name': 'Jane', 'age': 25}
]
with open('data.csv', 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['name', 'age']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for row in data:
writer.writerow(row) -
JSON文件:适合存储半结构化的数据。示例代码如下:
import json
data = [
{'name': 'John', 'age': 30},
{'name': 'Jane', 'age': 25}
]
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
数据库存储
-
MySQL :使用
pymysql
库连接和操作MySQL数据库。示例代码如下:import pymysql
连接数据库
conn = pymysql.connect(host='localhost', user='root', password='password', database='test')
cursor = conn.cursor()创建表
create_table_sql = """
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
age INT
)
"""
cursor.execute(create_table_sql)插入数据
data = [
('John', 30),
('Jane', 25)
]
insert_sql = "INSERT INTO users (name, age) VALUES (%s, %s)"
cursor.executemany(insert_sql, data)提交事务
conn.commit()
关闭连接
cursor.close()
conn.close() -
MongoDB :使用
pymongo
库连接和操作MongoDB数据库。示例代码如下:from pymongo import MongoClient
连接数据库
client = MongoClient('mongodb://localhost:27017/')
db = client['test']
collection = db['users']插入数据
data = [
{'name': 'John', 'age': 30},
{'name': 'Jane', 'age': 25}
]
collection.insert_many(data)关闭连接
client.close()
此篇用于个人学习总结,内容暂且记录到此,如有错误或者不同见解劳烦各位learner指出!!!感谢阅读!!!