Python 网络爬虫代码完善与扩展:多线程抓取、延迟控制与错误处理
以下是 Python 网络爬虫代码示例,该示例演示了如何使用多线程、延迟控制和错误处理来完善和扩展代码,使之更加高效和稳定。
import requests
from bs4 import BeautifulSoup
import configparser
import concurrent.futures
import logging
import time
def login(session, url, username, password):
try:
response = session.get(url, timeout=5)
response.raise_for_status()
soup = BeautifulSoup(response.content, 'html.parser')
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.update({'username': username, 'password': password})
response = session.post(url + action, data=form_data, timeout=5)
response.raise_for_status()
if '登录失败' in response.text:
logging.error('登录失败')
return False
return True
except requests.exceptions.RequestException as e:
logging.error('请求异常: %s', e)
except Exception as e:
logging.error('发生异常: %s', e)
return False
def crawl_website(session, url):
try:
response = session.get(url, timeout=5)
response.raise_for_status()
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')
save_filename = config.get('File', 'SaveFilename')
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(max_workers=5) as executor:
futures = [executor.submit(crawl_website, session, url) for url in urls]
for future, url in zip(concurrent.futures.as_completed(futures), 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_data(result, f'{save_filename}_{result['url']}')
print(f'数据已保存到文件 {save_filename}_{result['url']}')
print('--------------------')
time.sleep(1) # 添加延迟,避免对目标网站造成过大压力
else:
logging.error('登录失败')
if __name__ == '__main__':
main()
代码优化与扩展:
-
多线程抓取: 使用
concurrent.futures.ThreadPoolExecutor实现多线程抓取,可以提高爬取效率。 -
延迟控制: 在每个抓取任务完成后添加延迟,避免对目标网站造成过大压力。
-
错误处理: 在每个函数中使用
try...except块处理可能出现的异常,确保代码稳定运行。
如何进一步完善和扩展代码:
-
添加代理服务器: 使用代理服务器可以隐藏你的真实 IP 地址,避免被目标网站屏蔽。
-
使用数据库存储数据: 使用数据库可以更加方便地存储和管理爬取到的数据。
-
添加日志记录: 添加日志记录可以帮助你跟踪代码运行情况和排查问题。
-
使用更高级的爬虫框架: 使用更高级的爬虫框架可以简化爬虫代码开发,例如 Scrapy 框架。
-
处理动态网页: 对于动态网页,可以使用 Selenium 框架来模拟浏览器行为,获取网页内容。
希望这些信息能帮助你!如果你还有其他问题,请随时提问。
原文地址: https://www.cveoy.top/t/topic/ojF 著作权归作者所有。请勿转载和采集!