Python爬虫进阶:并发爬取网站内容并保存
Python爬虫进阶:并发爬取网站内容并保存
这篇博客将带你学习如何使用Python编写一个更强大的网络爬虫,它能够并发地爬取网站内容,并提取关键信息保存到本地文件。
以下是代码示例:
import requests
from bs4 import BeautifulSoup
import configparser
import concurrent.futures
import logging
def login(session, url, username, password):
# 发送GET请求,获取登录页面的HTML内容
response = session.get(url)
response.raise_for_status()
# 解析登录页面的HTML内容
soup = BeautifulSoup(response.content, 'html.parser')
# 获取登录表单的POST地址和对应的表单数据
login_form = soup.find('form', id='loginForm')
action = login_form['action']
inputs = login_form.find_all('input')
form_data = {input.get('name'): input.get('value') for input in inputs}
# 更新表单数据中的用户名和密码字段
form_data['username'] = username
form_data['password'] = password
# 发送POST请求进行登录
response = session.post(url + action, data=form_data)
response.raise_for_status()
if '登录失败' in response.text:
logging.error('登录失败')
return False
return True
def crawl_website(session, url):
try:
# 发送HTTP请求,获取网页内容
response = session.get(url)
response.raise_for_status() # 检查请求是否成功
# 解析HTML内容
soup = BeautifulSoup(response.content, 'html.parser')
# 爬取网站标题
title = soup.title.text.strip() if soup.title else None
# 爬取网站链接
links = [link['href'] for link in soup.find_all('a', href=True)]
# 爬取网站内容
content = soup.find('div', class_='content').get_text(strip=True) if soup.find('div', class_='content') else None
return {
'url': url,
'title': title,
'links': links,
'content': content
}
except requests.exceptions.RequestException as e:
logging.error('请求异常: %s', e)
except Exception as e:
logging.error('发生异常: %s', e)
return None
def save_data(data, filename):
# 将爬取的数据保存到文件
with open(filename, 'w', encoding='utf-8') as file:
file.write(f'网站 {data['url']} 的标题: {data.get('title', '未找到')}
')
file.write('网站链接:
')
for link in data.get('links', []):
file.write(f'{link}
')
file.write(f'网站 {data['url']} 的内容:
{data.get('content', '未找到')}')
def main():
# 配置日志记录
logging.basicConfig(filename='web_crawler.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
# 读取配置文件
config = configparser.ConfigParser()
config.read('config.ini')
url = config.get('Website', 'URL')
username = config.get('Login', 'Username')
password = config.get('Login', 'Password')
# 创建会话对象
with requests.Session() as session:
# 登录
if login(session, url, username, password):
# 并发爬取多个网页
urls = [url + f'?page={i}' for i in range(1, 6)]
with concurrent.futures.ThreadPoolExecutor() as executor:
# 使用列表推导式,同时执行多个爬取任务
results = [executor.submit(crawl_website, session, url) for url in urls]
for future, url in zip(concurrent.futures.as_completed(results), urls):
result = future.result()
if result:
# 输出网站标题
print(f'网站 {result['url']} 的标题:', result.get('title', '未找到'))
# 输出网站链接
print(f'网站 {result['url']} 的链接:')
if result['links']:
for link in result['links']:
print(link)
else:
print('未找到网站链接')
# 输出网站内容
print(f'网站 {result['url']} 的内容:')
if result['content']:
print(result['content'])
else:
print('未找到网站内容')
# 将数据保存到文件
save_filename = f'web_crawler_{result['url'].split('=')[-1]}.txt'
save_data(result, save_filename)
print(f'数据已保存到文件 {save_filename}')
print('--------------------')
else:
logging.error('登录失败')
if __name__ == '__main__':
main()
代码改进点:
- 并发爬取: 使用
concurrent.futures.ThreadPoolExecutor实现并发,提高爬取效率。 - 数据保存: 将爬取到的标题、链接、内容等信息保存到本地文件中,方便后续分析和使用。
- 错误处理: 使用
try-except块捕获网络请求和数据处理过程中可能出现的异常,增强代码健壮性。 - 日志记录: 使用
logging模块记录程序运行过程中的错误信息,方便排查问题。
进一步改进:
- 数据存储: 可以考虑使用数据库 (如 SQLite、MySQL) 存储爬取的数据,以便更方便地进行管理和查询。
- 反爬机制: 一些网站可能会采取反爬机制,需要根据实际情况添加相应的应对措施,例如设置请求头、随机延迟等。
- 代码结构: 随着功能的增加,可以考虑将代码模块化,提高代码的可读性和可维护性。
希望这篇文章能够帮助你更好地理解如何使用 Python 编写网络爬虫。 Happy coding!
原文地址: http://www.cveoy.top/t/topic/nNX 著作权归作者所有。请勿转载和采集!