
Python爬虫保存断点的方法包括使用数据库保存进度、使用文件保存进度、使用缓存保存进度。其中,使用数据库保存进度是一种常用且高效的方法。
详细描述:使用数据库保存进度时,可以在爬虫开始时创建一个数据库表,用于记录每个URL的状态(如已爬取、未爬取、失败等)。在每次爬取过程中,更新数据库中的状态信息。这样,即使爬虫中途意外停止,也可以从数据库中读取上次的进度,继续爬取未完成的部分。这种方法不仅能够持久化数据,还能方便管理和查询爬取进度。
一、使用数据库保存进度
使用数据库保存进度的方法可以确保数据的持久性和可靠性。常用的数据库包括MySQL、PostgreSQL、SQLite等。以下是具体的实现步骤:
1. 创建数据库表
首先,需要创建一个数据库表,用于存储爬取进度。该表至少需要包含以下字段:
- id:主键
- url:需要爬取的URL
- status:爬取状态(如未爬取、已爬取、爬取失败等)
- last_update:最后更新的时间
CREATE TABLE crawl_progress (
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. 插入待爬取的URL
在开始爬取之前,需要将待爬取的URL插入到数据库表中。
import sqlite3
conn = sqlite3.connect('crawler.db')
cursor = conn.cursor()
urls = ['http://example.com/page1', 'http://example.com/page2', 'http://example.com/page3']
for url in urls:
cursor.execute("INSERT INTO crawl_progress (url) VALUES (?)", (url,))
conn.commit()
conn.close()
3. 更新爬取状态
在爬取过程中,需要根据爬取结果更新数据库表中的状态。
import requests
import sqlite3
import time
def crawl(url):
try:
response = requests.get(url)
response.raise_for_status()
# 处理爬取结果
return 'success'
except requests.RequestException:
return 'failed'
conn = sqlite3.connect('crawler.db')
cursor = conn.cursor()
while True:
cursor.execute("SELECT id, url FROM crawl_progress WHERE status = 'pending' LIMIT 1")
row = cursor.fetchone()
if row is None:
break
id, url = row
status = crawl(url)
cursor.execute("UPDATE crawl_progress SET status = ?, last_update = ? WHERE id = ?", (status, time.time(), id))
conn.commit()
conn.close()
4. 从断点继续爬取
如果爬虫中途停止,再次启动时可以从数据库中读取未爬取的URL,继续爬取。
conn = sqlite3.connect('crawler.db')
cursor = conn.cursor()
while True:
cursor.execute("SELECT id, url FROM crawl_progress WHERE status = 'pending' LIMIT 1")
row = cursor.fetchone()
if row is None:
break
id, url = row
status = crawl(url)
cursor.execute("UPDATE crawl_progress SET status = ?, last_update = ? WHERE id = ?", (status, time.time(), id))
conn.commit()
conn.close()
二、使用文件保存进度
使用文件保存进度是一种简单且容易实现的方法。可以将爬取的URL和状态信息保存在文件中,在爬虫中途停止时,从文件中读取进度继续爬取。
1. 保存进度到文件
在每次爬取过程中,将当前爬取的URL和状态信息写入文件。
import requests
import json
def crawl(url):
try:
response = requests.get(url)
response.raise_for_status()
# 处理爬取结果
return 'success'
except requests.RequestException:
return 'failed'
urls = ['http://example.com/page1', 'http://example.com/page2', 'http://example.com/page3']
progress_file = 'progress.json'
def save_progress(progress):
with open(progress_file, 'w') as f:
json.dump(progress, f)
def load_progress():
try:
with open(progress_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
return []
progress = load_progress()
for url in urls:
if any(p['url'] == url for p in progress):
continue
status = crawl(url)
progress.append({'url': url, 'status': status})
save_progress(progress)
2. 从文件中读取进度
在爬虫中途停止时,可以从文件中读取进度,继续爬取未完成的部分。
progress = load_progress()
for url in urls:
if any(p['url'] == url and p['status'] == 'success' for p in progress):
continue
status = crawl(url)
progress.append({'url': url, 'status': status})
save_progress(progress)
三、使用缓存保存进度
使用缓存保存进度是一种高效且快速的方法。可以使用Redis等缓存数据库来保存爬取进度。
1. 安装Redis
首先,需要安装Redis并启动Redis服务。
sudo apt-get install redis-server
sudo service redis-server start
2. 安装Redis客户端
在Python中,需要安装Redis客户端库。
pip install redis
3. 保存进度到Redis
在每次爬取过程中,将当前爬取的URL和状态信息写入Redis。
import requests
import redis
def crawl(url):
try:
response = requests.get(url)
response.raise_for_status()
# 处理爬取结果
return 'success'
except requests.RequestException:
return 'failed'
urls = ['http://example.com/page1', 'http://example.com/page2', 'http://example.com/page3']
r = redis.Redis()
for url in urls:
if r.get(url) == b'success':
continue
status = crawl(url)
r.set(url, status)
4. 从Redis中读取进度
在爬虫中途停止时,可以从Redis中读取进度,继续爬取未完成的部分。
for url in urls:
if r.get(url) == b'success':
continue
status = crawl(url)
r.set(url, status)
四、综合使用多种方法
在实际应用中,可以综合使用多种方法来保存爬取进度,以提高爬虫的可靠性和健壮性。例如,可以同时使用数据库和文件保存进度,当其中一种方法失效时,可以使用另一种方法进行恢复。
1. 使用数据库和文件保存进度
在每次爬取过程中,同时将当前爬取的URL和状态信息写入数据库和文件。
import requests
import sqlite3
import json
import time
def crawl(url):
try:
response = requests.get(url)
response.raise_for_status()
# 处理爬取结果
return 'success'
except requests.RequestException:
return 'failed'
urls = ['http://example.com/page1', 'http://example.com/page2', 'http://example.com/page3']
progress_file = 'progress.json'
def save_progress(progress):
with open(progress_file, 'w') as f:
json.dump(progress, f)
def load_progress():
try:
with open(progress_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
return []
progress = load_progress()
conn = sqlite3.connect('crawler.db')
cursor = conn.cursor()
for url in urls:
if any(p['url'] == url for p in progress):
continue
cursor.execute("SELECT status FROM crawl_progress WHERE url = ?", (url,))
row = cursor.fetchone()
if row and row[0] == 'success':
continue
status = crawl(url)
progress.append({'url': url, 'status': status})
save_progress(progress)
cursor.execute("INSERT OR REPLACE INTO crawl_progress (url, status, last_update) VALUES (?, ?, ?)", (url, status, time.time()))
conn.commit()
conn.close()
2. 从断点继续爬取
在爬虫中途停止时,可以从数据库和文件中读取进度,继续爬取未完成的部分。
progress = load_progress()
conn = sqlite3.connect('crawler.db')
cursor = conn.cursor()
for url in urls:
if any(p['url'] == url and p['status'] == 'success' for p in progress):
continue
cursor.execute("SELECT status FROM crawl_progress WHERE url = ?", (url,))
row = cursor.fetchone()
if row and row[0] == 'success':
continue
status = crawl(url)
progress.append({'url': url, 'status': status})
save_progress(progress)
cursor.execute("INSERT OR REPLACE INTO crawl_progress (url, status, last_update) VALUES (?, ?, ?)", (url, status, time.time()))
conn.commit()
conn.close()
通过综合使用多种方法,可以提高爬虫的可靠性,确保在爬虫中途停止时能够从断点继续爬取,避免重复爬取已经完成的部分。
相关问答FAQs:
如何在Python爬虫中实现断点续爬功能?
为了实现断点续爬,您可以使用持久化存储,如数据库或本地文件,来记录已爬取的页面或数据。每次开始爬虫时,程序可以检查存储中已记录的内容,并从最后的断点继续爬取,避免重复抓取。
使用哪些工具或库可以方便地实现断点续爬?
在Python中,您可以使用requests库进行网络请求,结合sqlite3或pandas等库存储爬取状态和数据。这些工具可以帮助您有效地管理和更新爬虫的进度。
爬虫过程中如何处理网络异常或请求超时?
处理网络异常和请求超时是确保爬虫稳定性的重要环节。您可以使用try-except结构来捕获异常,并设置重试机制,例如通过time.sleep()等待一段时间后重试请求。此外,可以记录当前爬取状态,以便在异常发生时能及时恢复。












