Python中如何实现Django+Selenium+Requests+Chrome的多请求爬虫程序?
目前使用 threading 创建多个线程,因为要使用帐号模拟登陆,所以帐号数就等于可创建线程数。
用 queue 分配任务队列,如果所有的帐号都处于使用状态,就.put 这个请求而不去执行爬虫,然后等一个线程爬取完毕就.get 一下继续爬,如此循环。
可能我描述的不大清楚,请问各位大佬有没有好的思路?
Python中如何实现Django+Selenium+Requests+Chrome的多请求爬虫程序?
3 回复
要搞一个结合Django、Selenium、Requests和Chrome的多请求爬虫,核心思路是把Selenium用于需要JS渲染的页面,Requests用于高效抓取静态内容,然后用Django来管理和调度这些任务。下面是一个可以直接跑的示例:
1. 首先,用Django创建一个任务模型和视图来管理爬虫请求:
# models.py
from django.db import models
class CrawlTask(models.Model):
url = models.URLField()
use_selenium = models.BooleanField(default=False) # 标记是否需要JS渲染
status = models.CharField(max_length=20, default='pending')
result = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
2. 实现核心爬虫逻辑,根据需求选择工具:
# crawler.py
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
class HybridCrawler:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
def setup_selenium(self):
"""配置Chrome无头模式"""
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=chrome_options)
driver.set_page_load_timeout(30)
return driver
def fetch_with_requests(self, url):
"""用Requests获取静态内容"""
try:
response = self.session.get(url, timeout=10)
response.raise_for_status()
return response.text
except requests.RequestException as e:
return f"Error: {str(e)}"
def fetch_with_selenium(self, url, wait_for=None, timeout=10):
"""用Selenium获取动态内容"""
driver = self.setup_selenium()
try:
driver.get(url)
# 如果需要等待特定元素
if wait_for:
WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((By.CSS_SELECTOR, wait_for))
)
time.sleep(2) # 额外等待确保完全渲染
return driver.page_source
except Exception as e:
return f"Selenium Error: {str(e)}"
finally:
driver.quit()
def process_task(self, task_data):
"""处理单个爬虫任务"""
if task_data.get('use_selenium'):
# 对于需要JS渲染的页面
html = self.fetch_with_selenium(
task_data['url'],
wait_for=task_data.get('wait_for')
)
else:
# 对于静态页面
html = self.fetch_with_requests(task_data['url'])
# 这里可以添加解析逻辑
return {
'url': task_data['url'],
'html_length': len(html) if isinstance(html, str) else 0,
'success': not html.startswith('Error')
}
3. 创建Django视图来处理并发请求:
# views.py
from django.http import JsonResponse
from django.views import View
from concurrent.futures import ThreadPoolExecutor, as_completed
from .crawler import HybridCrawler
import json
class BatchCrawlView(View):
def post(self, request):
try:
tasks = json.loads(request.body)
results = []
crawler = HybridCrawler()
# 使用线程池并发执行
with ThreadPoolExecutor(max_workers=5) as executor:
future_to_task = {
executor.submit(crawler.process_task, task): task
for task in tasks
}
for future in as_completed(future_to_task):
task = future_to_task[future]
try:
result = future.result(timeout=30)
results.append(result)
except Exception as e:
results.append({
'url': task['url'],
'error': str(e),
'success': False
})
return JsonResponse({'results': results})
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
4. 最后配置URL和简单的前端测试:
# urls.py
from django.urls import path
from .views import BatchCrawlView
urlpatterns = [
path('api/crawl/', BatchCrawlView.as_view(), name='batch_crawl'),
]
使用示例:
# 发送批量请求
import requests
import json
tasks = [
{
'url': 'https://httpbin.org/html',
'use_selenium': False # 静态页面用Requests
},
{
'url': 'https://example.com/dynamic-content',
'use_selenium': True, # 动态页面用Selenium
'wait_for': '.loaded-content' # 可选:等待特定元素
}
]
response = requests.post('http://localhost:8000/api/crawl/',
json=tasks)
print(response.json())
关键点:
- 用
use_selenium标志智能选择工具 - Requests处理简单页面,Selenium处理JS渲染
- 线程池实现并发,避免单个任务阻塞
- Django提供任务管理和API接口
记得先装依赖:pip install django selenium requests,还有对应Chrome版本的ChromeDriver。
总结:根据页面类型选工具,Django做调度。
无语 涉及 celery + 线程池?
实测,谷歌浏览器同时在线个数为 60 个,,一般主机
你把爬虫做成一个异步任务,一个接口接受任务,接受了任务就往队列推送一个任务,然后返回一个任务 ID,爬虫任务执行完了就把结果保存起来,再做一个接口查询爬虫的任务结果。

