1. 项目概述
本项目通过使用
Selenium
和
Pandas
库来实现对大麦网演出信息的自动爬取,并将数据保存为
CSV
文件。爬虫能够抓取演出信息如图片地址、演出标题、演出地址、时间、售票价格及售票状态。多线程技术用于提高爬取效率,日志记录用于监控程序运行状态
2. 技术栈
Selenium:用于模拟浏览器操作,自动化执行点击、查找元素等任务
Pandas:用于将爬取的数据存储为
CSV
文件,方便后续数据分析和处理
Queue 和 Threading:用于多线程处理爬虫任务,使得爬取过程更加高效
Logging:记录程序运行的关键步骤,便于调试和监控
3. 项目流程
3.1初始化 Selenium:启动 Chrome 浏览器,设置为无头模式,确保后台运行
3.2爬取网页数据:模拟用户点击,爬取每个演出的图片、标题、地址、时间、售票价格等信息
3.3数据存储:将数据保存为
CSV
文件,合并并去重
3.4多线程处理:使用
Queue
和
threading
进行任务并行执行,提高爬取效率
4.代码分步讲解
4.1 依赖库的导入以及日志配置
import os
import threading
import time
from queue import Queue
import pandas as pd
from selenium.webdriver.chrome.service import Service
from selenium import webdriver
from selenium.webdriver.common.by import By
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
os
:用于文件操作,判断 CSV 文件是否存在threading
和Queue
:用于多线程和任务队列pandas
:用于处理和保存数据。selenium
:用于模拟浏览器操作,访问网页并提取数据logging
:用于记录程序的运行过程,便于调试和监控
4.2 Selenium 驱动初始化
stop_event = threading.Event()
service = Service("./driver/chromedriver.exe")
options = webdriver.ChromeOptions()
options.add_argument("--headless")
driver = webdriver.Chrome(service=service, options=options)
click_query = Queue()
Service("./driver/chromedriver.exe")
:指定 Chrome 浏览器驱动程序的位置webdriver.ChromeOptions()
:设置浏览器选项options.add_argument("--headless")
:启用无头模式,后台运行浏览器,不会显示窗口Queue()
:创建一个队列,存储爬取任务的 XPath 路径stop_event
:用于控制线程的终止
4.3 核心函数
spider,利用xpath定位到需要的数据
def spider():
while not stop_event.is_set() and not click_query.empty():
type1 = driver.find_element(By.XPATH, click_query.get(timeout=3))
type1.click()
logging.info(f"正在获取{type1.text}数据")
type2 = type1.text
# 获取图片地址
img_urls = driver.find_elements(By.XPATH, "//div[@class='item__box']/div/a/img")
img_url = [item.get_attribute("data-src") for item in img_urls]
# 获取演出标题
titles = driver.find_elements(By.XPATH, "//div[@class='items__txt']/div[1]")
title = [item.text for item in titles]
# 获取地址
addresses = driver.find_elements(By.XPATH, "//div[@class='items__txt']/div[2]")
address = [item.text for item in addresses]
# 获取时间
times = driver.find_elements(By.XPATH, "//div[@class='items__txt']/div[3]")
time1 = [item.text for item in times]
# 获取售票价格和状态
pricesAndStatus = driver.find_elements(By.XPATH, "//div[@class='items__txt__price']")
pAS = [item.text for item in pricesAndStatus]
# 保存数据
save_data(img_url, title, address, time1, pAS, type2)
driver.implicitly_wait(20)
- 循环控制:通过
while
循环不断执行任务队列中的点击操作,直到爬完所有页面或stop_event
触发 - 页面点击:通过
driver.find_element(By.XPATH, ...)
定位元素并执行点击 - 数据抓取:通过 XPath 获取网页中各类数据,如图片地址、演出标题、地址、时间、售票状态等,并存储在列表中
- 保存数据:调用
save_data
函数将数据保存
4.4 数据提取函数
save_data,
CSV 文件写入函数
save_csv
def save_data(img_url, titles, address, times, pricesAndStatus, type2):
data = [{"序号": i+1, "剧照图片地址": img_url[i], "标题": titles[i], "地址": address[i], "时间": times[i], "售票价格和售票状态": pricesAndStatus[i]} for i in range(len(titles))]
save_csv(data, type2)
def save_csv(data, type2):
df = pd.DataFrame(data)
file_name = f"{type2}.csv"
if os.path.exists(file_name):
existing_df = pd.read_csv(file_name)
combined_df = pd.concat([existing_df, df], ignore_index=True)
unique_df = combined_df.drop_duplicates(subset=['标题'], keep='first')
unique_df.to_csv(file_name, index=False, encoding='utf-8-sig')
else:
df.to_csv(file_name, index=False, encoding='utf-8-sig')
logging.info(f"数据保存成功!")
- 数据整合:将爬取到的各类数据整合为字典,每一项数据对应一个演出,按序号排列
- 保存至 CSV:调用
save_csv
函数保存数据至 CSV 文件 - 文件判断:如果 CSV 文件已存在,则读取现有文件并将新数据合并,避免重复写入
- 去重:使用
drop_duplicates
函数对数据去重,以标题为标准,保留第一条重复数据 - 保存数据:保存最终的去重数据为
CSV
文件,使用 UTF-8 编码避免乱码
4.5 主程序
if __name__ == '__main__':
driver.get("https://search.damai.cn/search.htm/")
driver.implicitly_wait(20)
driver.find_element(By.XPATH, "//div[@class='factor-content']/span[14]").click()
title_click = [
"/html/body/div[2]/div[2]/div[1]/div[1]/div[2]/div/div/div/span[3]",
"/html/body/div[2]/div[2]/div[1]/div[1]/div[2]/div/div/div/span[4]",
"/html/body/div[2]/div[2]/div[1]/div[1]/div[2]/div/div/div/span[5]",
]
for item in title_click:
click_query.put(item)
spider()
time.sleep(3)
driver.quit()
- 访问目标页面:通过
driver.get
访问大麦网搜索页 - 模拟用户点击:点击页面上的某个筛选条件
- 设置任务队列:将多个 XPath 地址添加到
click_query
队列中,用于后续的点击操作 - 启动爬虫:调用
spider
函数开始数据爬取,爬取完成后关闭浏览器
5. 多线程的使用
项目使用了
Queue
来存储任务列表,并通过
spider
函数逐个执行点击操作,爬取不同页面的数据。
多线程技术可以通过
threading
实现更高效的数据抓取,适用于大规模数据爬取任务。对于本项目,虽然未实现多线程并发,但可以通过多线程进一步优化性能。
6.可能遇到的问题与解决方式
6.1Selenium 驱动和浏览器版本匹配
问题描述
Selenium 需要浏览器驱动与本地 Chrome 浏览器版本相匹配。即如果 Chrome 浏览器升级了,必须确保对应的
chromedriver
版本也进行了相应的更新。
解决方案
定期检查 Chrome 浏览器版本,并从 ChromeDriver 网站下载与浏览器匹配的驱动。
6.2防止反爬虫机制
问题描述
部分网站可能会对频繁访问的行为启用反爬虫机制,比如验证码、IP 封禁等。
解决方案
增加
user-agent
:模拟真实的浏览器访问,避免过于频繁或异常的请求行为。
设置合适的延迟:通过
time.sleep()
减缓爬取频率,避免频繁的页面访问触发反爬虫。
使用代理 IP:当 IP 被封禁时,启用代理 IP 继续爬取。
动态浏览器配置:使用
random_user_agent
生成不同的
user-agent
,模拟不同设备和浏览器访问。
版权归原作者 有理走遍天下724 所有, 如有侵权,请联系我们删除。