位置: 文档库 > Python > 使用python Selenium爬取内容并存储MySQL数据库的实例图解

使用python Selenium爬取内容并存储MySQL数据库的实例图解

TidalShade 上传于 2021-05-16 00:32

《使用Python Selenium爬取内容并存储MySQL数据库的实例图解》

在数据驱动的时代,网络爬虫技术已成为获取公开数据的重要手段。本文将通过一个完整的实例,详细讲解如何使用Python的Selenium库模拟浏览器操作爬取网页内容,并将数据存储到MySQL数据库中。该方案适用于需要动态渲染页面的场景(如JavaScript生成的页面),相比Requests+BeautifulSoup的静态爬取方案更具优势。

一、环境准备与工具安装

在开始编码前,需要配置以下环境:

  1. Python 3.6+环境
  2. Selenium WebDriver(ChromeDriver/GeckoDriver)
  3. MySQL数据库(5.7+版本)
  4. 相关Python库:selenium、pymysql、time、re

1.1 安装Python依赖库

pip install selenium pymysql

1.2 下载WebDriver

根据浏览器版本下载对应驱动:

将驱动文件放入系统PATH路径或项目根目录

1.3 MySQL数据库准备

CREATE DATABASE IF NOT EXISTS web_data DEFAULT CHARSET utf8mb4;
USE web_data;

CREATE TABLE IF NOT EXISTS articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    url VARCHAR(512) UNIQUE,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

二、Selenium基础操作详解

2.1 浏览器初始化配置

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def init_browser(headless=True):
    chrome_options = Options()
    if headless:
        chrome_options.add_argument('--headless')  # 无头模式
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
    
    driver = webdriver.Chrome(
        executable_path='./chromedriver',  # 驱动路径
        options=chrome_options
    )
    return driver

2.2 元素定位方法对比

方法 示例 适用场景
ID定位 find_element_by_id("element_id") 唯一ID元素
CSS选择器 find_element_by_css_selector(".class > #id") 复杂结构定位
XPath find_element_by_xpath("//div[@class='content']/p[1]") 层级定位

2.3 等待机制实现

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def safe_find_element(driver, locator, timeout=10):
    try:
        return WebDriverWait(driver, timeout).until(
            EC.presence_of_element_located(locator)
        )
    except Exception as e:
        print(f"元素查找失败: {e}")
        return None

# 使用示例
element = safe_find_element(
    driver, 
    (By.CSS_SELECTOR, ".article-title")
)

三、完整爬虫实现步骤

3.1 项目结构规划

project/
├── config.py          # 配置文件
├── crawler.py         # 爬虫主逻辑
├── database.py        # 数据库操作
└── requirements.txt   # 依赖清单

3.2 配置文件设计

# config.py
MYSQL_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': 'your_password',
    'database': 'web_data',
    'charset': 'utf8mb4'
}

CRAWLER_CONFIG = {
    'start_url': 'https://example.com/articles',
    'max_pages': 50,
    'sleep_time': (1, 3)  # 随机延迟范围
}

3.3 数据库操作模块

# database.py
import pymysql
from config import MYSQL_CONFIG

class MySQLHelper:
    def __init__(self):
        self.conn = pymysql.connect(
            host=MYSQL_CONFIG['host'],
            user=MYSQL_CONFIG['user'],
            password=MYSQL_CONFIG['password'],
            database=MYSQL_CONFIG['database'],
            charset=MYSQL_CONFIG['charset']
        )
        self.cursor = self.conn.cursor()
    
    def insert_article(self, title, content, url):
        sql = """
        INSERT INTO articles (title, content, url)
        VALUES (%s, %s, %s)
        ON DUPLICATE KEY UPDATE 
        title=VALUES(title), content=VALUES(content)
        """
        try:
            self.cursor.execute(sql, (title, content, url))
            self.conn.commit()
            return True
        except Exception as e:
            print(f"数据库插入错误: {e}")
            self.conn.rollback()
            return False
    
    def close(self):
        self.cursor.close()
        self.conn.close()

3.4 核心爬虫实现

# crawler.py
import time
import random
from selenium.webdriver.common.by import By
from database import MySQLHelper
from config import CRAWLER_CONFIG

class ArticleCrawler:
    def __init__(self):
        self.driver = init_browser()
        self.db = MySQLHelper()
    
    def random_sleep(self):
        t = random.uniform(*CRAWLER_CONFIG['sleep_time'])
        time.sleep(t)
    
    def parse_article(self, article_url):
        self.driver.get(article_url)
        self.random_sleep()
        
        try:
            title = self.driver.find_element_by_css_selector("h1.title").text
            content = self.driver.find_element_by_css_selector("div.article-content").text
            return {
                'title': title,
                'content': content,
                'url': article_url
            }
        except Exception as e:
            print(f"文章解析错误: {e}")
            return None
    
    def crawl_list_page(self, list_url):
        self.driver.get(list_url)
        self.random_sleep()
        
        articles = []
        elements = self.driver.find_elements_by_css_selector(".article-item a")
        for elem in elements:
            article_url = elem.get_attribute("href")
            article_data = self.parse_article(article_url)
            if article_data:
                self.db.insert_article(
                    article_data['title'],
                    article_data['content'],
                    article_data['url']
                )
                articles.append(article_data)
        return articles
    
    def run(self):
        current_page = 1
        while current_page 

四、进阶优化技巧

4.1 反爬策略应对

  • 代理IP池:使用selenium-wirescrapy-proxy-pool
  • Cookie管理:
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

caps = DesiredCapabilities.CHROME
caps['goog:loggingPrefs'] = {'performance': 'ALL'}
driver = webdriver.Chrome(desired_capabilities=caps)

4.2 分布式爬虫架构

使用Redis实现任务队列:

import redis

class TaskQueue:
    def __init__(self):
        self.r = redis.Redis(host='localhost', port=6379, db=0)
    
    def push_url(self, url):
        self.r.lpush('crawler:tasks', url)
    
    def pop_url(self):
        _, url = self.r.brpop('crawler:tasks', timeout=10)
        return url.decode('utf-8')

4.3 数据清洗与存储优化

import re
from html import unescape

def clean_content(text):
    # 去除HTML标签
    text = re.sub(r']+>', '', text)
    # 解码HTML实体
    text = unescape(text)
    # 去除多余空格
    text = ' '.join(text.split())
    return text.strip()

五、常见问题解决方案

5.1 元素找不到的调试技巧

  • 使用开发者工具检查元素是否在iframe中
  • 添加显式等待:
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.visibility_of_element_located((By.ID, "dynamic-element")))

5.2 数据库连接问题处理

import pymysql
from pymysql import MySQLError

try:
    conn = pymysql.connect(**MYSQL_CONFIG)
except MySQLError as e:
    if e.args[0] == 2003:  # 连接失败
        print("无法连接到MySQL服务器")
    elif e.args[0] == 1045:  # 认证失败
        print("数据库用户名或密码错误")

5.3 性能优化建议

  • 使用连接池管理数据库连接
  • 批量插入数据:
def batch_insert(self, articles):
    sql = """
    INSERT INTO articles (title, content, url)
    VALUES (%s, %s, %s)
    """
    params = [(a['title'], a['content'], a['url']) for a in articles]
    try:
        self.cursor.executemany(sql, params)
        self.conn.commit()
    except Exception as e:
        print(f"批量插入错误: {e}")
        self.conn.rollback()

六、完整项目部署指南

6.1 日志系统实现

import logging

def setup_logger():
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler('crawler.log'),
            logging.StreamHandler()
        ]
    )
    return logging.getLogger('article_crawler')

# 使用示例
logger = setup_logger()
logger.info("爬虫启动")

6.2 定时任务配置(使用APScheduler)

from apscheduler.schedulers.blocking import BlockingScheduler

def scheduled_crawl():
    crawler = ArticleCrawler()
    try:
        crawler.run()
    finally:
        crawler.close()

scheduler = BlockingScheduler()
scheduler.add_job(scheduled_crawl, 'cron', hour='8', minute='30')
scheduler.start()

6.3 Docker化部署

# Dockerfile
FROM python:3.9-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "crawler.py"]

构建并运行:

docker build -t web-crawler .
docker run -d --name crawler web-crawler

七、总结与扩展思考

本文通过完整的代码实例,演示了从浏览器自动化到数据持久化的全流程。关键技术点包括:

  1. Selenium的元素定位与等待机制
  2. MySQL数据库的连接管理与批量操作
  3. 异常处理与日志记录
  4. 反爬策略与性能优化

扩展方向建议:

  • 结合Scrapy框架实现分布式爬取
  • 使用Elasticsearch构建搜索系统
  • 添加数据可视化模块(如Matplotlib/Pyecharts)

关键词:Python爬虫、Selenium、MySQL数据库、WebDriver、数据持久化、反爬策略、动态页面爬取无头浏览器

简介:本文详细讲解了使用Python Selenium库爬取动态网页内容并存储到MySQL数据库的完整实现方案,包含环境配置、核心代码实现、异常处理、性能优化及部署指南,适合需要处理JavaScript渲染页面的数据采集场景。

《使用python Selenium爬取内容并存储MySQL数据库的实例图解.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档