1. 背景
在工作中经常需要获取外部数据,使用 Python 结合 Gitlab 实现一套定时爬取数据的工具是常见需求。本文针对 Python 爬虫的核心知识进行梳理,涵盖基础语法、网络请求、数据解析、正则表达式及 Selenium 自动化等模块,帮助开发者快速入门。
本文详细介绍了 Python 爬虫技术的快速入门指南。内容涵盖 Python 基础语法、requests 网络请求库的使用、BeautifulSoup 数据解析方法、正则表达式匹配技巧以及 Selenium 浏览器自动化操作。文章通过具体代码示例讲解了 GET/POST 请求、标签查找、CSS 选择器、元素定位及模拟鼠标操作等核心技能,并补充了遵守 robots.txt 协议、设置请求头、控制请求频率及异常处理等最佳实践,旨在帮助开发者构建稳定高效的爬虫程序。

在工作中经常需要获取外部数据,使用 Python 结合 Gitlab 实现一套定时爬取数据的工具是常见需求。本文针对 Python 爬虫的核心知识进行梳理,涵盖基础语法、网络请求、数据解析、正则表达式及 Selenium 自动化等模块,帮助开发者快速入门。
需要掌握的核心知识点:
下面针对上述每部分进行详细介绍。
学习任何编程语言都必须掌握其语法知识,Python 也不例外。如果有其他编程语言基础,上手 Python 会非常快。
在 Python 中,定义一个变量分为两步:命名和赋值。这两个步骤在同一行代码中完成。
version = '1'
Python 中的变量命名规范与其他开发语言类似,基本规则如下:
import 来命名变量,因为它是 Python 的保留字。D 和 d 是两个不同的变量。Python 中有 6 种基本数据类型:数字(Numbers)、字符串(String)、列表(List)、字典(Dictionary)、元组(Tuple)和集合。
在 Python 中定义变量后需明确对应的数据类型。同时可以使用 del 变量名 删除对象引用。
num = 0
pi = 3.14
name = "abc"
# 定义列表 [],列表元素可以修改
list_data = [12, 2, 212, 44, 5, 6]
dic = {
"k1": "v1",
"k2": "v2",
}
# 集合类型用 set 标识,创建使用 { } 或者 set()
s1 = {1, 2, 3, 3, 2, 2, 2, 1, "1"}
# 元组用 () 表示,元组的元素不能修改
tuple_data = ('runoob', 786, 2.23, 'john', 70.2)
del s1
对于每种数据类型,都有一些常用的方法:
| 数据类型 | 常用方法 |
|---|---|
| 字符串 | - [:]:截取字符串的一部分(切片),遵循左闭右开原则;[]:通过索引获取字符;in:如果包含给定字符返回 True;not in:如果不包含给定字符返回 True;capitalize():首字符转大写;endswith(suffix):检查是否以指定后缀结束;find(str):检测 str 是否包含,返回索引或 -1;index(str):同 find,但不包含则报错;len(string):返回长度;replace(old, new):替换字符串;rstrip():删除末尾空格;split(str):分割字符串。 |
| 列表/元组 | - len(list):元素个数;list(seq):转换为列表;list.append(obj):末尾添加对象;list.index(obj):查找匹配项索引;list.remove(obj):移除第一个匹配项;list.clear():清空列表。 |
| 字典 | - len(dict):键的总数;key in dict:判断键是否存在;dict.items():返回 (键,值) 元组数组;dict.keys():返回所有键;dict.values():返回所有值。 |
字符串类型转换通过 str() 函数可以将一个变量转换为字符串类型。
int(x):将 x 转换为整数。float(x):将 x 转换为浮点数。complex(x):将 x 转换为复数,虚部为 0。complex(x, y):将 x 和 y 转换为复数。str(x):将对象 x 转换为字符串。在 Python 中运算符基本与其他开发语言一致,常用的有算术运算符、比较运算符、逻辑运算符、赋值运算符等。
算术运算符包括加 (+)、减 (-)、乘 (*)、除 (/)、取模 (%)、幂 (**)、整除 (//)。
比较运算符包括等于 (==)、不等于 (!=)、大于 (>)、小于 (<)、大于等于 (>=)、小于等于 (<=)。
逻辑运算符包括与 (and)、或 (or)、非 (not)。
Python 的控制语句分为条件语句和循环语句,前者为 if 语句,后者为 for 语句和 while 语句。
if 语句主要用于条件判断,满足特定条件执行相应语句。
if 条件:
代码块 1
else:
代码块 2
示例:
grade = 60
if grade >= 60:
print("及格")
else:
print("不及格")
for 语句常用于完成指定次数的重复操作。
for i in 序列:
要重复执行的代码
示例:
numbers = [12, 2, 212, 44, 5, 6]
for item in numbers:
print(item)
while 语句用于在指定条件成立时重复执行操作。
while 条件:
要重复执行的代码
示例:
a = 60
while a < 70:
print(a)
a = a + 1
Python 提供了诸多的内置函数,但在开发时也需要经常用到自定义函数。
在 Python 中使用 def 关键字定义一个函数。
def 函数名 (参数):
实现函数功能的代码
如果需要返回值,则需要使用 return 进行返回。
def data_transform():
# 具体的实现逻辑
return True
要使用模块,就需要安装和导入模块。模块的两种导入方法:import 语句导入法和 from 语句导入法。
import 语法会导入模块内所有方法,一般如果用包的方法较多可以选择;from 模块名 import 函数名:导入某块中某个函数。import math # 导入 math 模块
import turtle # 导入 turtle 模块
from math import sqrt # 导入 math 模块中的单个函数
from turtle import forward, backward, right, left # 导入 turtle 模块中的多个函数
模块的安装使用 pip install 指令:
pip install "SomeProject"
爬虫需要了解基础的网络请求和基础的 HTML 知识,能够认识基础的 HTML 标签。
requests 包可以模拟浏览器发起 HTTP 或 HTTPS 协议的网络请求,从而获取网页源代码。
使用也比较简单,先安装模块:pip install requests。
GET 请求 比如抓取百度首页的信息。
import requests
response = requests.get(url='https://www.baidu.com')
print(response.text)
POST 请求
req_url = "https://juejin.org/post"
formdata = {
'username': 'admin',
'password': 'a123456',
}
req_header = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
response = requests.post(
req_url,
data=formdata,
headers=req_header
)
print(response.text)
通过 requests 模块发送网络请求非常简单,容易上手。
BeautifulSoup 模块是一个 HTML/XML 解析器,主要用于解析和提取 HTML/XML 文档中的数据。该模块不仅支持 Python 标准库中的 HTML 解析器 lxml,而且支持许多功能强大的第三方解析器。
在使用前先通过 pip 指令安装模块:pip install beautifulsoup4。
以请求百度首页为例。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
print(soup.prettify())
打印输出以下信息(HTML 源码结构):
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="content-type"/>
<title>百度一下,你就知道</title>
</head>
<body>
...
</body>
</html>
通过 BeautifulSoup 库可以将请求的网址信息按照标签进行转换展示。下面学习 BeautifulSoup 提供的标签操作方法。
依照上一节中的百度首页为例,下面分别介绍 BeautifulSoup 中常用的方法。
查找指定标签名 在网页源码中,存在很多类型的标签。通过标签名进行定位只能返回其中的第一个标签。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
print(soup.input)
查找指定属性的标签
标签的属性有:name、class、id 等,我们使用 find 或 find_all 方法查找标签对应的所有属性。
import requests
from bs4 import BeautifulSoup
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
# 查找 class 属性为 bg s_ipt_wr 的标签
bg_tags = soup.find_all(class_='bg s_ipt_wr')
for tag in bg_tags:
print(tag)
# 查找 name = rsv_idx
idx = soup.find(attrs={'name': 'rsv_idx'})
print(idx)
在上面的示例中,我们通过 find_all 方法查找所有 class_='bg s_ipt_wr' 的标签。因为 class 这个单词本身是 Python 的保留字,所以 BeautifulSoup 模块中的 class 属性在末尾添加了下划线来进行区分。其他标签属性,如 id 属性,则没有添加下划线。
通过标签名 + 属性查找 通过指定标签名 + 属性值可以实现更准确的查找。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
# 查找 input 标签且属性 name = rsv_idx
idx = soup.find('input', attrs={'name': 'rsv_idx'})
print(idx)
在上一小节中介绍了 find 方法用于查找标签,使用 select() 函数可以根据指定的选择器返回所有符合条件的标签。常用的选择器有 id 选择器、class 选择器、标签选择器和层级选择器。
1. 标签选择器
根据指定的标签进行筛选。在 find 中根据指定标签名查找时只会返回第一个匹配项。使用 select 标签返回所有。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
input_tag = soup.select('input')
print(input_tag)
2. id 选择器 id 选择器是根据 id 值查找对应的标签。格式 '#id 值'。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
input_tag = soup.select('#kw')
print(input_tag)
3. class 选择器 class 选择器根据 class 属性值查找对应的标签,格式为 '.class 属性值'。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
input_tag = soup.select('.s_ipt')
print(input_tag)
4. 层级筛选器
在 HTML 中标签嵌套很常见,标签在不同的层级形成嵌套结构。通过 标签>标签 这种指向结构来定位。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
# 查找所有 div 标签下 div 标签的 id 属性值为 lg 的标签
div_tag = soup.select('div>div>#lg')
print(div_tag)
# 查找 form 标签下所有的 input 标签
input_tag = soup.select('form>input')
print(input_tag)
">" 在层级选择器中表示向下找一个层级,中间不能有其他层级。如果中间有空格表示中间可以有多个层级。
找到标签后,我们需要读取标签对应的内容或者属性。
提取标签内容
获取标签后我们需要查找标签中的内容,可以利用 string 或 text 来提取。string 属性返回的是指定标签的直系文本,即直接存在于该标签中的文本,而不是存在于该标签下的其他标签中的文本。text 属性返回的则是指定标签下的所有文本。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
div_tag = soup.select('div>a')
print(div_tag[0].string)
print(div_tag[0].text)
从标签中提取属性
对于找到的标签,提取属性直接使用 tag['属性表'] 即可。
if __name__ == '__main__':
url = "https://www.baidu.com"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
div_tag = soup.select('form>input')
print(div_tag[0]['name'])
print(div_tag[0]['type'])
至此,我们基本完成了对 BeautifulSoup 库的学习。
正则表达式是一种用于匹配和操作文本的强大工具,它是由一系列字符和特殊字符组成的模式,用于描述要匹配的文本模式。正则表达对网页源代码的字符串进行匹配,从而提取出需要的数据。
普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。
| 符号 | 描述 |
|---|---|
| \W | 匹配任何非单词字符。等价于'[^A-Za-z0-9_]'。 |
| \w | 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 |
| \s | 匹配任何空白字符,包括空格、制表符、换页符等等。 |
| \S | 匹配任何非空白字符。 |
| \d | 匹配一个数字字符。等价于 [0-9]。 |
| \D | 匹配一个非数字字符。等价于 [^0-9]。 |
示例代码:
import re
if __name__ == '__main__':
str_val = 'kdd199ok98 a123 343'
print(re.findall('\W', str_val)) # 匹配任何非单词字符
print(re.findall('\w', str_val)) # 匹配任何单词字符
print(re.findall('\S', str_val)) # 匹配任何非空白字符
print(re.findall('\s', str_val)) # 匹配空白字符
print(re.findall('\D', str_val)) # 匹配非数字
print(re.findall('\d', str_val)) # 匹配数字
元字符是正则表达式中有特殊含义的字符,可以设置字符的匹配模式。
| 符号 | 描述 |
|---|---|
| $ | 匹配输入字符串的结尾位置。 |
| ( ) | 标记一个子表达式的开始和结束位置。 |
| * | 匹配前面的子表达式零次或多次。 |
| + | 匹配前面的子表达式一次或多次。 |
| . | 匹配除换行符 \n 之外的任何单字符。 |
| [ | 标记一个中括号表达式的开始。 |
| ? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。 |
| \ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用。 |
| ^ | 匹配输入字符串的开始位置。 |
| {n} | n 是一个非负整数。匹配确定的 n 次。 |
| {n,} | n 是一个非负整数。至少匹配 n 次。 |
| {n,m} | m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。 |
示例代码:
import re
if __name__ == '__main__':
str_val = 'akdd1d199ok98 d123 3438'
print(re.findall('8$', str_val)) # 匹配以 8 结尾的字符
print(re.findall('^a', str_val)) # 匹配以 a 开头的字符
print(re.findall('(d1)?', str_val)) # 匹配 d1 零次或一次
print(re.findall('(d1)+', str_val)) # 匹配 d1 一次或多次
print(re.findall('[ad]', str_val)) # 匹配字符集合 [ad]
正则表达式基础,但是想灵活运用起来还需要多加练习,太灵活可以组装很多模式。
通过 requests 模块可以实现对一些静态网页的请求,对于一些动态与浏览器需要交互的地址则不能满足。而 Selenium 模块则能控制浏览器发送请求,并和获取到的网页中的元素进行交互,因此,只要是浏览器发送请求能得到的数据,Selenium 模块也能直接得到。
使用 Selenium 模块需要先下载和安装浏览器驱动程序,然后在编程时通过 Selenium 模块实例化一个浏览器对象,再通过浏览器对象访问网页和操作网页元素。
安装比较简单,直接使用 pip install selenium 安装就行了。比较重要的是安装浏览器驱动程序。
在对应官网中可以下载对应版本的浏览器驱动程序。
查看自己浏览器版本,在浏览器中输入:chrome://version/
选择对应的电脑端系统,比如 Mac 系统,下载对应的即可。解压之后放到环境路径或者项目中都行,只要在使用时指定对应的环境即可。
这里以打开百度网站为例。我将 webdriver 放到项目路径中。
from selenium import webdriver
if __name__ == '__main__':
browser = webdriver.Chrome(executable_path='./chromedriver_mac64/chromedriver')
browser.get('https://www.baidu.com')
webdriver 返回的 browser 对象中,提供了丰富的 API 用于操作浏览器。
| 方法 | 描述 |
|---|---|
browser.maximize_window() | 最大化浏览器 |
browser.current_url | 当前网页 url |
browser.get_cookie() | 当前网页用到的 cookie 信息 |
browser.name | 当前浏览器驱动名称 |
browser.title | 当前网页标题 |
browser.page_source | 获取当前网页源代码 |
browser.refresh() | 刷新当前网页 |
browser.quit() | 关闭浏览器 |
browser.close() | 关闭当前网页 |
browser.back() | 返回上一页 |
完成了网页的访问后,如果需要模拟用户操作网页元素,则需要先通过标签来定位网页元素。
find_element(self, by=By.ID, value=None) 查找元素,其中 By.ID 是枚举类型:
使用示例:
from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == '__main__':
browser = webdriver.Chrome(executable_path='./chromedriver_mac64/chromedriver')
browser.get('https://www.baidu.com')
tag1 = browser.find_element(by=By.ID, value='form')
print(tag1.get_attribute("class"))
找到标签后,就可以通过 get_attribute 方法获取对应的属性值。
常用的鼠标操作有单击、双击、右击、长按、拖动、移动等,模拟这些操作需要用到 Selenium 模块中的 ActionChains 类。它提供了以下方法:
下面以打开百度首页的图片链接为例:
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
if __name__ == '__main__':
browser = webdriver.Chrome(executable_path='./chromedriver_mac64/chromedriver')
browser.get('https://www.baidu.com')
alink = browser.find_element(by=By.LINK_TEXT, value='图片')
print(alink.get_attribute("href"))
actions = ActionChains(browser)
actions.click(alink).perform()
运行成功后,会首先打开百度首页,然后跳转到百度图片页面。
在实际开发爬虫程序时,除了掌握技术细节,还需注意以下几点以确保程序的稳定性和合规性。
在爬取网站前,应检查网站的 robots.txt 文件(通常位于 https://域名/robots.txt),了解网站允许和禁止爬取的目录。尊重网站的爬取规则是爬虫开发者的基本职业道德。
大多数网站会识别 User-Agent 字段来判断请求来源。为了模拟正常浏览器行为,建议在请求头中设置合适的 User-Agent,避免被服务器直接拦截。
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers)
频繁的请求可能会导致 IP 被封禁或对目标服务器造成压力。建议使用 time.sleep() 函数在请求之间加入延迟,或者使用随机休眠时间。
import time
import random
time.sleep(random.uniform(1, 3)) # 随机休眠 1 到 3 秒
网络请求可能会因为超时、连接失败等原因出错。应使用 try-except 块捕获异常,保证程序不会因单次请求失败而崩溃。
try:
response = requests.get(url, timeout=5)
response.raise_for_status()
except Exception as e:
print(f"请求失败:{e}")
通过本次学习,掌握了 Python 爬虫的核心流程:从基础语法入手,利用 requests 发起网络请求,使用 BeautifulSoup 解析 HTML 结构,配合正则表达式提取特定数据,以及使用 Selenium 处理动态渲染页面。在实际应用中,还需结合反爬策略、代理 IP 等技术手段提升爬虫的稳定性。希望本文能为初学者提供清晰的入门指引。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online