Python Crawler

Cealivanus Kwan Lv3

简单爬取网页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from urllib.request import urlopen

# 打开网址,得到响应
url = "https://cealivanus.github.io/"
resp = urlopen(url)

# 从响应中得到内容,在终端输出
print(resp.read().decode("UTF-8"))

# 将网页信息(html)保存在同级目录文件中
# python 文件读写
with open("myblog.html", mode='w', encoding="utf-8") as f:
f.write(resp.read().decode("UTF-8")) # 读取到网页源代码
print("save over!")

可以在pycharm上选择用本地浏览器打开,成功爬取网页!

Web 请求全过程

1.服务器渲染:

在服务器直接把数据和html整合在一起,同意返回给浏览器

可以在页面源代码中看到数据。

2.客户端渲染:

第一次请求只要一个html骨架,第二次请求拿到数据,进行数据展示。

页面源代码中没有数据。

HTTP 协议

http表示当前数据传输遵循http协议(超文本传输协议)

该协议下,一条信息三块内容:

请求:

1.请求行 -> 请求方式(get/post)请求url地址 协议

2.请求头 -> 服务器需要的附加信息

3.请求体 -> 一般是一些请求参数

响应:

1.状态行 -> 协议 状态码(如404 500 等)

2.响应头 -> 客户端需要的附加信息

3.响应体 -> 服务器返回的真正客户端需要使用的内容(html,json等)

请求头与响应头可能含有爬虫需要的信息

请求头:

1.__User-Agent__:请求载体的身份标识(请求来源)

2.Referer:防盗链(请求来源的页面,用于反爬)

3.cookie:本地字符串数据信息(用户登录信息,反爬token)

响应头:

1.cookie:本地字符串数据信息

2.其它字符串:一般是token字样,防止攻击与反爬

请求方式:

GET:显式提交(浏览查询)(直接显示在 url 中)

POST:隐式提交(更新数据)

Requests 模块介绍

安装:pip

搜狗搜索具有简单的反爬机制,可以通过伪装浏览器User-Agent的方式处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests

url = "https://www.sogou.com/web?query=董宇辉"

# 简单的反爬处理方式:
# 面对反爬机制,对象警告是否是正常浏览器操作
# 伪装成浏览器
# 网页 - F12 - 网络 - 标头header - 拉到下边找 User-Agent
dic = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0"
}

# 将ua信息导入resp
resp = requests.get(url, headers=dic)

print(resp)
print(resp.text) # 将页面源代码转化成文本

requests 对 urllib 做了简化操作

也可以用输入的方式实现交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests

q = input("请输入待查内容:")

url = f'https://www.sogou.com/web?query={q}'

# 简单的反爬处理方式:
# 面对反爬机制,对象警告是否是正常浏览器操作
# 伪装成浏览器
# 网页 - F12 - 网络 - 标头header - 拉到下边找 User-Agent
dic = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0"
}

# 将ua信息导入resp
resp = requests.get(url, headers=dic)

print(resp)
print(resp.text) # 将页面源代码转化成文本

案例:查找豆瓣电影分类排行榜 - 喜剧片

网址:https://movie.douban.com/typerank?type_name=%E5%96%9C%E5%89%A7&type=24&interval_id=100:90&action=

image-20250329202336070

浏览器抓包工具:火狐浏览器 HackBar

F12 -> Network -> XHR (过滤次要响应)-> Headers

在左栏寻找需要爬取信息所在的响应

编写爬虫代码:

1
2
3
4
5
import requests

url = "https://movie.douban.com/j/chart/top_list?type=24&interval_id=100:90&action=&start=0&limit=20"

resp = requests.get(url=url) # 该页面显示为 GET 请求方式

上下两份代码相同,建议使用下面的方式,更具有可读性,便于修改

1
2
3
4
5
6
7
8
9
10
11
12
13
import requests

url = "https://movie.douban.com/j/chart/top_list"

param = {
"type": "24",
"interval_id": "100: 90",
"action": "",
"start": 0,
"limit": 20,
}

resp = requests.get(url=url, params=param) # 该页面显示为 GET 请求方式

运行后无响应:

image-20250329203408084

这是被网站反爬的结果

下面是想尽办法绕过反爬机制

尝试打印 headers 信息

1
print(resp.request.headers)

image-20250329203557287

我们需要挨个检查结果参数。

首先尝试处理 User-Agent

从网页找到 ua 位置

image-20250329203749216

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
import requests
import json # 用于保存json文档

url = "https://movie.douban.com/j/chart/top_list"

param = {
"type": "24",
"interval_id": "100:90", # 要注意这里,不要有中文冒号,不要有空格,不然只有[]没有返回
"action": "",
"start": 0,
"limit": 20,
}

# 处理 user-agent
hds = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:136.0) Gecko/20100101 Firefox/136.0"
}

resp = requests.get(url=url, params=param, headers=hds) # 将 headers 装填

print(resp.json()) # 控制台打印信息

data = resp.json()

# 推荐 movies.json
with open("movies.txt", "w", encoding="utf-8") as f:
f.write(json.dumps(data, ensure_ascii=False, indent=2)) # 格式化输出

运行:成功读取并保存信息!!!

image-20250329210042114

控制台打印只有一长行不便阅读,遂保存到文件中。

程序最后不要忘记加上

1
resp.close() # 关掉resp

2 数据解析

从整个网页冗杂的信息中提取我们需要的信息。

三种数据解析方式: re bs4 xpath

2.1 re解析

Regular Expression 正则表达式

正则的语法:使用元字符进行排列组合用来匹配字符串

元字符:具有固定含义的特殊字符

常用元字符:

代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
\n 匹配一个换行符
\t 匹配一个制表符
^ 匹配字符串的开始(在集合字符里[^a]表示非(不匹配)的意思
$ 匹配字符串的结束
\W 匹配非字母或数字或下划线或汉字 大写字母表示反义词
\D 匹配非数字
\S 匹配非空白符
a|b 匹配字符a或字符b
() 匹配括号内的表达式,也表示一个组
[] 表示字符组(元组)

常用反义字符

代码/语法 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

常用限定符

代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
  • 标题: Python Crawler
  • 作者: Cealivanus Kwan
  • 创建于 : 2025-03-29 17:09:39
  • 更新于 : 2025-04-05 18:27:38
  • 链接: https://redefine.ohevan.com/2025/03/29/Python-Crawler/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。