python爬虫学习笔记

owofile Lv5

python爬虫学习笔记

我记得当初刚接触编程的时候,就想要学习爬虫,因为那时候我对自己的定位是偏向黑客方面的23333,感觉很酷,但当时连一门编程语言都没有搞明白,所以也学的一塌糊涂。

这也说明了学习顺序的重要性,还记得之前学渗透的时候,提前搞明白了通信原理,学习的速度快了很多,反之则迟迟无法理解。

回到主题,这次我学习的是python爬虫。为什么选择python,因为python提供了很多的包,这让我们实现功能更加的方便,当然你也可以使用JAVA,C等去写,但对于新手而言,我还是推荐python,同时Python 提供了多线程和异步编程的支持,可以提高爬虫的效率,在抓取大量数据时尤为重要。

什么是爬虫

爬虫(Web Crawler) 是一种自动访问互联网并提取特定信息的程序或脚本。它通过模拟浏览器行为,访问网页并获取数据。

主要功能:

  1. 数据采集:从网站上收集文本、图片等信息,广泛应用于市场研究、数据分析等领域。
  2. 搜索引擎索引:搜索引擎使用爬虫来抓取和索引网页,以便提供相关的搜索结果。
  3. 内容监控:监测特定网站的更新,如价格变化、新闻发布等。
  4. 机器学习数据准备:为模型训练收集大量数据。

工作原理:

  1. 初始化:从一个或多个种子 URL 开始。
  2. 发送请求:向种子 URL 发送 HTTP 请求以获取网页内容。
  3. 解析数据:解析 HTML 文档,提取所需的信息。
  4. 存储数据:将提取的数据保存到数据库或文件中。
  5. 提取新链接:从当前网页中提取新的链接,并加入待爬取列表。
  6. 循环执行:重复上述步骤,直到满足停止条件。

注意事项:

  • 遵循法律法规及网站的 robots.txt 文件规则。
  • 控制爬取频率,避免对目标网站造成影响。

爬取百度主页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#导包
from urllib.request import urlopen
import re
# 设置网站路径
url = "http://www.baidu.com"
# 打开网站并返回结果
resp = urlopen(url)
html\_str = resp.read().decode("utf-8")
# 编写一个正则表达式来匹配card\_title的值
# 假设card\_title总是以"card\_title": "开始并以"结尾
pattern = r'"card\_title": "(.\*?)"'
# 使用re.findall查找所有匹配的card\_title
card\_titles = re.findall(pattern, html\_str, re.DOTALL)
# 打印所有找到的card\_title
for title in card\_titles:
print(title)

这段代码实现了爬取baidu.com的页面,然后获取主页的新闻标题并且打印在控制台

代码解释

可以看到开头我导入了两个包,分别是urlopen 和 re,第一个包名字就很直观,打开url,因为我们只需要urlopen,所以可以看到from 来自 urllib.request 的 urlopen被我们单独拿出来导入了项目里。

而 re 是为了快速找到我们需要的字符串,通过re.findall方法按规则输入好相关参数就可以提取出来内容。

要注意的是,使用urlopen方法返回的结果如果是乱码,那就需要根据网页的编码设置去设置,不然是无法显示中文的,比如这里的baidu.com是utf-8,所以我们要调用阅读的方法然后设置好编码后再次返回结果,这次返回的就是整个正常的网页源代码。

Web请求过程刨析

现在的网站大体分为两种,静态网站和动态网站,顾名思义,静态网站的一些信息(如文本、图像等)直接包含在网页的 HTML 代码中,访问网页时能直接看到,而动态网站有些数据则需要在网页加载后通过 JavaScript 进行请求,这部分数据不会出现在源代码中。

所以想要获取到动态网站的数据,我们要理解其原理。

网页数据提取原理

在现代网页中,有些数据不是直接嵌入到 HTML 源代码中的,而是通过 JavaScript 进行动态加载。这些数据通常来自于额外的 API 请求。以下是这一过程的基本原理:

1. 网页结构

  • 静态内容:一些信息(如文本、图像等)直接包含在网页的 HTML 代码中,访问网页时能直接看到。
  • 动态内容:有些数据则需要在网页加载后通过 JavaScript 进行请求,这部分数据不会出现在源代码中。

2. 如何加载数据

当用户打开网页时,浏览器会:

  • 加载 HTML 文件。
  • 解析 HTML 中的 JavaScript 代码,执行其中的 AJAX 或 Fetch 请求,以从服务器获取更多数据。
  • 将这些数据插入到网页中,更新页面的内容。

3. 数据请求

  • API 请求:网页通常会向特定的 URL 发送 HTTP 请求(例如 GET 或 POST),并从服务器获取 JSON 或 XML 格式的数据。这些请求可以在浏览器的开发者工具中查看。

4. 如何抓取这种数据

要获取这些动态加载的数据,可以按照以下步骤操作:

  1. 使用开发者工具
    • 在浏览器中打开目标网页,右键点击元素并选择“检查”。
    • 切换到“网络”(Network)选项卡。
    • 刷新页面并观察所有的网络请求,找到返回所需数据的请求(通常是以 JSON 格式返回的数据)。
  2. 获取请求信息
    • 查看请求的 URL 和所需的头部信息(Headers)。
    • 确认请求方法(GET 或 POST)和请求参数(如果有的话)。
  3. 编写爬虫代码
    • 使用像 Requests 库发送相同的请求,从而获取并处理响应中的数据。

AJAX 请求及原理简介

因为我之前学过Web网站部署,所以理解前端和后端的通信原理,如果要学习python爬虫,理解网站请求的原理很重要。

什么是AJAX?

  • AJAX(Asynchronous JavaScript and XML)是一种用于在不重新加载整个页面的情况下,与服务器异步通信的技术。
  • 它允许网页动态更新内容,提升用户体验。

AJAX 的工作原理

  1. 用户操作:用户在网页上执行某个操作(例如点击按钮)。
  2. 发送请求:
    • 使用JavaScript创建一个AJAX请求。
    • 选择HTTP请求方法(如GET或POST),并设置请求的URL和参数。
  3. 后台通信:
    • AJAX请求被发送到服务器,服务器处理请求并返回数据(通常为JSON、XML或HTML格式)。
  4. 接收响应:
    • 页面通过JavaScript接收到服务器的响应。
  5. 更新页面:
    • 根据服务器返回的数据,动态更新网页的部分内容,而无需刷新整个页面。

请求类型

  • GET:用于从服务器请求数据,参数通过URL传递。
  • POST:用于向服务器发送数据,数据包含在请求体中,适合表单提交等操作。

主要优点

  • 提升用户体验:页面不需要完全刷新。
  • 减少带宽消耗:仅请求必要的数据。
  • 更快的交互:实现实时更新。

简单示例代码

以下是一个简单的AJAX请求示例,使用jQuery库:

1
2
3
4
5
6
7
8
9
10
11
12
13
$.ajax({
url: 'server-endpoint', // 服务器地址
type: 'GET', // 请求方式(GET/POST)
success: function(response) {
// 成功接收响应后执行的代码
console.log(response);
$('#result').html(response); // 更新页面内容
},
error: function(error) {
// 处理错误
console.error('请求失败:', error);
}
});

Requests入门

Requests 是一个用于发送 HTTP 请求的 Python 库,它提供了一个简单而直观的 API,方便开发者与 Web 进行交互。以下是对 Requests 的简单介绍,包括其特点和一些基本用法。

Requests 简介

  • 易于使用Requests 库的设计旨在简化 HTTP 请求的过程,使得用户能够以极少的代码完成复杂的请求操作。
  • 支持各种 HTTP 方法:包括 GETPOSTPUTDELETEHEAD 等。
  • 自动处理 Cookies:能够轻松管理会话中的 Cookies。
  • 支持 URL 参数和表单数据:可以很方便地将参数附加到 URL 上或通过表单提交。
  • 响应对象:提供丰富的响应对象,包括状态码、响应内容、头信息等,方便获取和解析服务器返回的信息。

安装

要使用 Requests,首先需要安装它。可以使用 pip 来安装:

1
pip install requests

在国内可能因为因为网络波动出现安装失败,可以通过切换镜像源或者临时使用镜像源来下载

推荐使用清华镜像源:清华镜像源网站

我使用临时下载

1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple requests

基本用法

以下是一些常见操作的示例:

1. 发送 GET 请求

1
2
3
4
import requests
response = requests.get('https://api.example.com/data')
print(response.status\_code) # 输出状态码
print(response.json()) # 如果响应是 JSON 格式,可以直接解析为字典

2. 发送 POST 请求

1
2
3
4
5
6
7
8
import requests
data = {
'name': 'John',
'age': 30
}
response = requests.post('https://api.example.com/users', json=data)
print(response.status\_code)
print(response.text) # 输出响应内容

3. 添加 URL 参数

1
2
3
params = {'id': 123}
response = requests.get('https://api.example.com/users', params=params)
print(response.url) # 输出完整的请求 URL

4. 处理 Cookies

1
2
3
session = requests.Session() # 创建会话对象
response = session.get('https://api.example.com/login')
# 系统会自动处理 Cookies

5. 错误处理

1
2
3
4
5
6
7
try:
response = requests.get('https://api.example.com/data')
response.raise\_for\_status() # 检查响应是否成功,若不成功则引发异常
except requests.exceptions.HTTPError as err:
print(f"HTTP error occurred: {err}")
except Exception as err:
print(f"An error occurred: {err}")

爬取百度请求网页

使用Requests请求爬取自定义的数据,原理为正常状态下我们打开百度然后输入查询的内容,返回网页数据,在这个过程中,点击百度按钮后,浏览器发送get请求附带查询的内容,得到返回结果,在使用Requests的情况下,我们通过提前定义好url和查询内容的变量,使用方法requests.get(),进行模拟浏览器请求。

然后返回结果,分拣出我们想要的数据。

代码展示:

1
2
3
4
5
6
7
8
9
10
11
12
import requests
#导入req lib
#定义Url 当然你可以使用input去更加自由的检索想要的数据
url = "https://www.baidu.com/s?wd=阿梓"
#请求头 加入了设备的信息值后,能返回想要的数据,否则可能没办法获取成功
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
#调用req的get方法并且填写相关参数 这里是rul路径 和 headers请求头
resp = requests.get(url,headers=headers)
#打印到控制台,如果需要也可以保存在本地
print(resp.text)

我每次学习代码都习惯性的会加入自己的理解,比如我认为这一段代码实际上是一个功能,为了更加方便的调用这个功能,可以将它写成一个方法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import requests
def fetch\_data\_from\_baidu(search\_term):
"""
从百度获取搜索结果的 HTML 内容。
:param search\_term: 要搜索的关键词
:return: 搜索结果的 HTML 内容
"""
# 定义 URL,使用提供的搜索词进行格式化
url = f"https://www.baidu.com/s?wd={search\_term}"
# 请求头
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
# 发起 GET 请求
resp = requests.get(url, headers=headers)
# 检查请求是否成功
if resp.status\_code == 200:
return resp.text # 返回 HTML 内容
else:
print(f"请求失败,状态码:{resp.status\_code}")
return None # 如果请求失败返回 None
# 使用该方法,输入想要搜索的关键词
#主程序执行
if \_\_name\_\_ == "\_\_main\_\_":
term = "阿梓" # 或者通过 input() 获取用户输入
html\_content = fetch\_data\_from\_baidu(term)
if html\_content:
print(html\_content) # 打印返回的 HTML 内容

这样完善后,更加坚固,同时增加了报错的处理。

另外也可以将这个脚本功能写多个方法,然后通过导包就可以导入在其他脚本里调用方法了。这就是python的模块化编程,允许将功能分隔到不同的文件中便于管理和重用。

这里想到了,所以顺便提一嘴。

增加参数的请求

上一个案例增加了headers请求头,这是为了避免一些反爬的措施,初次之外,很多时候,我们使用get请求都需要增加参数,比如搜索的结果,页数,本质上都是传递参数,返回JSON结果,在做数据分析和筛选。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
url = 'https://api.example.com/search'
# 请求头
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',
'Accept-Language': 'en-US,en;q=0.9',
}
# 查询参数
params = {
'q': 'Python',
'page': 1,
'size': 10
}
response = requests.get(url, headers=headers, params=params)
#记得关闭resp,否则容易堵塞
resp.close()
# 打印请求的 URL、状态码和响应内容
print(f"请求的 URL: {response.url}")
print(f"状态码: {response.status\_code}")
print(response.json())

这次的案例是我使用chatgpt生成的,仅作为理解使用,可以看到请求的时候增加了params和headers。

  • Title: python爬虫学习笔记
  • Author: owofile
  • Created at : 2024-08-10 14:16:54
  • Updated at : 2025-04-11 21:18:27
  • Link: https://owofile.github.io/blog/2024/08/10/python爬虫学习笔记/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments