第一次接触Scrape Center的SSR系列关卡时,我完全被它精心设计的渐进式难度吸引了。这个系列就像游戏里的新手村,从最简单的页面抓取开始,逐步引入各种真实爬虫场景中会遇到的问题。对于刚入门爬虫的新手来说,这里简直就是完美的训练场。
SSR系列目前有四个关卡,每个关卡都针对不同的爬虫技术点。第一关SSR1是最基础的静态页面抓取,没有任何反爬措施,适合用来熟悉requests和BeautifulSoup的基本用法。第二关SSR2开始引入HTTPS证书问题,第三关SSR3增加了HTTP Basic认证,而第四关SSR4则设置了响应延迟。这种循序渐进的设计让学习者能够一步步掌握更复杂的爬虫技术。
我建议完全零基础的朋友可以从SSR1开始,哪怕你之前从未写过爬虫代码。这个关卡的数据结构非常规整,所有电影信息都清晰地展示在页面上,包括电影标题、类型、评分和剧情简介。抓取这样的数据就像在超市货架上拿商品一样直观。
在开始编写爬虫代码前,我习惯先用浏览器开发者工具(F12)分析目标页面结构。打开SSR1的第一页(https://ssr1.scrape.center/page/1),可以看到每部电影都以卡片形式展示,包含我们需要的所有信息。
通过检查元素,我发现几个关键点:
这种清晰的结构让数据提取变得非常简单。我通常会先写一个小脚本测试单个页面的抓取,确认没问题后再扩展到多页。
下面是我优化后的SSR1完整爬取代码,相比原始版本做了一些改进:
python复制import pandas as pd
import requests
from bs4 import BeautifulSoup
from tqdm import tqdm # 添加进度条显示
# 禁用SSL警告
requests.packages.urllib3.disable_warnings()
def scrape_ssr1():
base_url = 'https://ssr1.scrape.center/page/'
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'
}
all_data = []
# 使用tqdm显示进度
for page in tqdm(range(1, 11), desc='抓取进度'):
try:
# 获取列表页
list_url = f"{base_url}{page}"
response = requests.get(list_url, headers=headers, verify=False)
soup = BeautifulSoup(response.text, 'lxml')
# 提取每部电影的详情页链接
movie_links = [
'https://ssr1.scrape.center' + a['href']
for a in soup.find_all('a', class_='name')
]
# 遍历每个详情页
for link in movie_links:
detail_resp = requests.get(link, headers=headers, verify=False)
detail_soup = BeautifulSoup(detail_resp.text, 'lxml')
# 提取详细信息
movie_data = {
'链接': link,
'标题': detail_soup.find('h2', class_='m-b-sm').get_text(strip=True),
'类型': detail_soup.find('div', class_='categories').get_text('|', strip=True).replace('|', ', '),
'评分': detail_soup.find('span', class_='score').get_text(strip=True),
'简介': detail_soup.find('div', class_='drama').get_text(strip=True).replace('剧情简介', '')
}
all_data.append(movie_data)
except Exception as e:
print(f"第{page}页抓取出错: {str(e)}")
continue
# 保存为CSV
df = pd.DataFrame(all_data)
df.to_csv('ssr1_movies.csv', index=False, encoding='utf_8_sig')
print("数据已保存为ssr1_movies.csv")
if __name__ == '__main__':
scrape_ssr1()
这个版本增加了错误处理、进度显示,并且优化了数据清洗过程。特别是使用get_text()方法的strip参数可以自动去除多余空白字符,比手动replace更简洁。
当从SSR1转到SSR2时,我发现虽然代码可以直接运行,但控制台会不断弹出SSL证书验证失败的警告。这是因为SSR2使用了自签名证书,不被系统信任。
在实际项目中,我们通常会遇到三种情况:
对于测试环境或内部系统,忽略证书验证是常见做法。但要注意,在生产环境中忽略证书验证会带来安全风险。
SSR2的代码与SSR1基本相同,主要区别在于verify=False参数的设置。我建议将请求封装成函数,方便复用:
python复制def safe_request(url, headers, auth=None, timeout=None):
try:
response = requests.get(
url,
headers=headers,
verify=False, # 忽略证书验证
auth=auth,
timeout=timeout
)
response.raise_for_status() # 检查HTTP错误
return response
except requests.exceptions.RequestException as e:
print(f"请求失败: {str(e)}")
return None
这样在SSR1-SSR4的所有关卡中都可以使用这个统一的请求方法,只需要传入不同的参数即可。
SSR3引入了HTTP Basic认证,这是最简单的Web认证方式之一。服务器会在首次访问时返回401状态码,要求客户端提供用户名和密码。在Scrape Center中,用户名和密码都是"admin"。
这种认证方式虽然简单,但存在安全隐患,因为认证信息只是用Base64编码,没有加密。现在大多数网站都使用更安全的认证方式,如OAuth或JWT。
requests库提供了HTTPBasicAuth来简化认证过程。下面是处理SSR3的关键代码:
python复制from requests.auth import HTTPBasicAuth
def scrape_ssr3():
base_url = 'https://ssr3.scrape.center/page/'
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'
}
auth = HTTPBasicAuth('admin', 'admin')
# 使用之前封装的safe_request函数
response = safe_request(base_url+'1', headers=headers, auth=auth)
if response:
# 处理响应内容...
在实际项目中,我建议将认证信息存储在配置文件中,而不是硬编码在代码里。可以使用python-dotenv等库来管理敏感信息。
SSR4模拟了服务器响应慢的场景,每个请求都会延迟5秒左右。在实际爬取中,我们可能遇到更复杂的延迟情况,比如:
处理这类问题需要综合考虑超时设置、重试机制和请求间隔控制。
对于SSR4,最简单的解决方案是增加timeout值。但更好的做法是实现自动重试和自适应延迟:
python复制import time
from random import uniform
def scrape_with_retry(url, headers, max_retries=3, initial_timeout=15):
for attempt in range(max_retries):
try:
response = requests.get(
url,
headers=headers,
verify=False,
timeout=initial_timeout * (attempt + 1)
)
return response
except requests.exceptions.Timeout:
if attempt == max_retries - 1:
raise
# 随机等待1-3秒再重试
time.sleep(uniform(1, 3))
此外,对于大规模爬取,建议添加随机延迟来模拟人类操作:
python复制def random_delay(min=1, max=5):
time.sleep(uniform(min, max))
原始代码将数据存储在CSV中,对于小型项目足够了。但随着数据量增加,可以考虑:
完善的爬虫应该具备良好的错误处理和日志功能:
python复制import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='scrape.log'
)
def scrape_page(url):
try:
# 爬取逻辑...
except Exception as e:
logging.error(f"爬取{url}失败: {str(e)}")
raise
经过多次实战,我总结出几个提升爬虫效率的技巧:
python复制# 使用Session示例
session = requests.Session()
session.headers.update({'User-Agent': 'Mozilla/5.0...'})
session.verify = False
response = session.get('https://ssr1.scrape.center/page/1')
对于想要系统学习爬虫的朋友,我建议按照这样的目录结构组织代码:
code复制scrape_center_project/
├── config/ # 配置文件
│ ├── settings.py
│ └── credentials.py
├── spiders/ # 爬虫代码
│ ├── ssr1.py
│ ├── ssr2.py
│ ├── ssr3.py
│ └── ssr4.py
├── utils/ # 工具函数
│ ├── network.py
│ └── storage.py
├── data/ # 爬取结果
│ └── ssr1_movies.csv
└── requirements.txt
这种结构便于维护和扩展,当你想增加新的爬虫时,只需要在spiders目录下添加新文件,复用现有的工具函数。