1. 项目背景与需求分析
扬州作为长三角地区重要城市,近年来人才引进力度不断加大,人才公寓作为配套政策的重要组成部分,其房源信息的获取成为许多新就业人员的刚需。传统手动查询方式存在效率低下、信息分散等问题,而通过Selenium实现的自动化爬取方案能够有效解决这些痛点。
这个项目的核心价值在于:
- 实时性:自动获取最新房源信息,避免错过申请窗口期
- 全面性:一次性收集所有区域人才公寓数据,便于横向对比
- 便捷性:自动化处理登录、翻页等重复操作,解放人力
2. 技术方案设计
2.1 工具选型考量
选择Selenium而非传统requests库主要基于以下判断:
- 目标网站采用动态渲染,关键数据通过AJAX加载
- 需要模拟登录操作获取完整信息
- 存在验证码等交互环节需要人工干预
- 页面结构复杂,需要完整DOM环境进行元素定位
配套工具链:
- ChromeDriver:与主流浏览器兼容性最佳
- Pandas:数据清洗与结构化存储
- PyMySQL:持久化到本地数据库
2.2 系统架构设计
mermaid复制graph TD
A[启动浏览器] --> B[登录系统]
B --> C[设置筛选条件]
C --> D[遍历分页数据]
D --> E[解析房源信息]
E --> F[异常处理]
F --> G[数据存储]
3. 核心实现细节
3.1 环境配置要点
推荐使用conda创建独立环境:
bash复制conda create -n yangzhou_apt python=3.8
conda install -c conda-forge selenium pandas pymysql
ChromeDriver版本匹配建议:
- 查看Chrome版本:chrome://version/
- 下载对应驱动:https://chromedriver.chromium.org/downloads
- 配置系统PATH或指定executable_path
3.2 关键代码实现
登录模块示例:
python复制def login(driver):
driver.get('https://yzrcfw.yangzhou.gov.cn/login')
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'username'))
)
driver.find_element(By.ID, 'username').send_keys('your_username')
driver.find_element(By.ID, 'password').send_keys('your_password')
# 手动处理验证码后继续
input('完成验证码后按回车继续...')
数据提取逻辑:
python复制def parse_apartment(driver):
items = driver.find_elements(By.CSS_SELECTOR, '.apartment-item')
results = []
for item in items:
data = {
'title': item.find_element(By.CLASS_NAME, 'title').text,
'address': item.find_element(By.CLASS_NAME, 'address').text,
'price': float(item.find_element(By.CLASS_NAME, 'price').text[:-1]),
'area': float(item.find_element(By.CLASS_NAME, 'area').text[:-1]),
'update_time': datetime.strptime(
item.find_element(By.CLASS_NAME, 'time').text,
'%Y-%m-%d %H:%M'
)
}
results.append(data)
return results
4. 反爬应对策略
4.1 常见防护手段
目标网站可能存在的防护措施:
- 用户行为检测(鼠标轨迹、操作间隔)
- IP频率限制
- 验证码触发机制
- 动态token验证
4.2 解决方案实践
人性化操作模拟:
python复制from selenium.webdriver.common.action_chains import ActionChains
def human_like_click(element):
action = ActionChains(driver)
action.move_to_element(element).pause(random.uniform(0.5, 1.5)).click().perform()
IP代理轮换方案:
python复制PROXY_LIST = ['http://ip1:port', 'http://ip2:port']
def rotate_proxy():
proxy = random.choice(PROXY_LIST)
chrome_options.add_argument(f'--proxy-server={proxy}')
5. 数据存储与分析
5.1 存储方案对比
| 存储类型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| CSV | 无需数据库支持 | 查询效率低 | 快速验证阶段 |
| MySQL | 支持复杂查询 | 需要运维成本 | 中长期数据存储 |
| MongoDB | 灵活schema | 内存占用高 | 非结构化数据 |
5.2 数据分析示例
使用Pandas进行房源性价比分析:
python复制df = pd.read_sql('SELECT * FROM apartments', con=engine)
df['price_per_sqm'] = df['price'] / df['area']
top10 = df.sort_values('price_per_sqm').head(10)
6. 运维与优化
6.1 定时任务配置
使用APScheduler实现每日自动运行:
python复制from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
@sched.scheduled_job('cron', hour=2)
def daily_job():
main()
sched.start()
6.2 性能优化技巧
- 启用无头模式节省资源:
python复制chrome_options.add_argument('--headless')
- 禁用图片加载加速页面渲染:
python复制chrome_options.add_experimental_option(
"prefs", {"profile.managed_default_content_settings.images": 2}
)
7. 异常处理与日志
7.1 健壮性增强
关键异常捕获机制:
python复制try:
element = driver.find_element(By.CSS_SELECTOR, '.pagination-next')
human_like_click(element)
except NoSuchElementException:
print("已到达最后一页")
except ElementClickInterceptedException:
driver.execute_script("arguments[0].click();", element)
7.2 日志配置建议
结构化日志记录:
python复制import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger('apartment_spider')
handler = TimedRotatingFileHandler('logs/app.log', when='midnight', backupCount=7)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
8. 法律与合规要点
8.1 数据采集边界
需特别注意:
- 仅采集公开可见信息
- 不绕过任何登录限制
- 遵守robots.txt规定
- 设置合理请求间隔(建议≥3秒)
8.2 数据使用规范
合法使用建议:
- 明确标注数据来源
- 不用于商业牟利
- 定期清理历史数据
- 对敏感信息脱敏处理
9. 项目扩展方向
9.1 功能增强
- 价格波动预警系统
- 空置率分析模型
- 交通便利性评分
- 周边配套可视化
9.2 技术演进
- 结合OCR识别验证码
- 引入Scrapy-Redis分布式扩展
- 使用Playwright替代Selenium
- 增加自动化邮件通知功能
重要提示:实际开发中建议添加适当的延时和随机操作,控制请求频率在合理范围内,避免对目标服务器造成过大压力。