当前位置:   article > 正文

Python实战:使用selenium及BeautifulSoup4进行BOOS直聘信息爬取与数据累积【附源码】_python selenium boss

python selenium boss

运行环境要求

  • 操作系统:适用于Windows、macOS、Linux。
  • Python版本:Python 3.6及以上。
  • 依赖库
    • selenium:用于模拟浏览器操作。
    • webdriver_manager:自动管理驱动程序。
    • BeautifulSoup4:解析HTML页面。
    • pandas:数据处理和CSV文件操作。
    • logging:日志记录。
      pip install selenium webdriver_manager beautifulsoup4 pandas

设计思路

本项目旨在通过Selenium模拟用户浏览器行为,获取特定网站(如Boss直聘)上的职位信息,并利用BeautifulSoup解析这些信息。为了实现数据的持续累积而不是每次运行都覆盖原有数据,采用pandas进行数据合并和去重,最终将更新后的数据保存到CSV文件中。

具体实践

  1. 初始化Selenium WebDriver:配置ChromeDriver,启动Chrome浏览器实例。
    1. from selenium import webdriver
    2. from selenium.webdriver.chrome.service import Service
    3. from webdriver_manager.chrome import ChromeDriverManager
    4. options = webdriver.ChromeOptions()
    5. try:
    6. driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
    7. except Exception as e:
    8. logging.error(f"创建WebDriver时出错: {e}")
    9. raise
  2. 获取并保存Cookies:访问目标网站并手动登录,然后保存Cookies以便后续自动登录使用。
    1. def 获取cookie(driver, url):
    2. logging.info("开始获取cookie")
    3. driver.get(url)
    4. time.sleep(30) # 等待足够的时间手动登录并保存cookies
    5. cookies = driver.get_cookies()
    6. with open('cookies.json', 'w') as f:
    7. json.dump(cookies, f)
    8. logging.info("Cookie获取完毕并已保存")
  3. 加载Cookies实现自动登录:在后续的会话中加载之前保存的Cookies,实现自动登录。
    1. def 加载cookie(driver, cookie_file='cookies.json'):
    2. logging.info("开始加载cookie")
    3. with open(cookie_file, 'r') as f:
    4. cookies = json.load(f)
    5. for cookie in cookies:
    6. if 'expiry' in cookie:
    7. del cookie['expiry'] # 删除过期时间,避免格式错误
    8. driver.add_cookie(cookie)
    9. logging.info("Cookie加载完毕")
  4. 爬取职位信息:访问职位列表页面,使用BeautifulSoup解析页面,提取职位相关信息。
    1. from bs4 import BeautifulSoup
    2. from selenium.webdriver.support.ui import WebDriverWait
    3. from selenium.webdriver.support import expected_conditions as EC
    4. from selenium.webdriver.common.by import By
    5. def 获取职位信息(driver, base_url, pages=1):
    6. logging.info("开始获取职位信息")
    7. 职位信息_list = []
    8. for i in range(1, pages + 1):
    9. url = f'{base_url}&page={i}'
    10. driver.get(url)
    11. WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "job-card-wrapper")))
    12. soup = BeautifulSoup(driver.page_source, 'html.parser')
    13. jobs = soup.find_all('li', class_='job-card-wrapper')
    14. # 提取并添加职位信息到列表中...
    15. return pd.DataFrame(职位信息_list)
  5. 数据去重与累积:读取已有的数据文件(如果存在),将新抓取的数据与旧数据合并,去除重复项,然后保存更新后的数据。
    1. import pandas as pd
    2. if os.path.exists(data_file):
    3. existing_data = pd.read_csv(data_file)
    4. else:
    5. existing_data = pd.DataFrame()
    6. 新职位信息 = 获取职位信息(driver, base_url, pages=5)
    7. 更新后的职位信息 = pd.concat([existing_data, 新职位信息], ignore_index=True).drop_duplicates(subset=['职位名称', '公司名称'])
    8. 更新后的职位信息.to_csv(data_file, index=False, encoding='utf-8-sig')

技术要点

  • Selenium的高级应用:包括但不限于Cookies的处理、显式等待(WebDriverWait)等技巧,以确保页面加载完成并成功获取数据。
  • BeautifulSoup的灵活运用:精确地定位和提取所需的HTML元素。
  • Pandas的数据处理能力:有效地合并、去重和保存数据。

项目复盘

  • 挑战
    • 页面结构变化导致的数据提取失败。
    • 网站反爬虫机制的应对。
    • 数据去重逻辑的设计。
  • 解决方案
    • 定期检查目标网站的页面结构,及时更新选择器。
    • 合理设置请求间隔,使用Cookies模拟登录状态,减少被封概率。
    • 利用pandas强大的数据处理功能,根据特定字段进行去重。

 完整源码

  1. import logging
  2. from selenium import webdriver
  3. from selenium.webdriver.chrome.service import Service
  4. from webdriver_manager.chrome import ChromeDriverManager
  5. from bs4 import BeautifulSoup
  6. import pandas as pd
  7. import os
  8. from selenium.webdriver.support.ui import WebDriverWait
  9. from selenium.webdriver.support import expected_conditions as EC
  10. from selenium.webdriver.common.by import By
  11. import time
  12. import json
  13. # 设置日志记录
  14. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  15. def 获取cookie(driver, url):
  16. # 访问指定的URL并等待用户手动登录,然后保存cookies
  17. logging.info("开始获取cookie")
  18. driver.get(url)
  19. time.sleep(30) # 等待足够的时间手动登录并保存cookies
  20. cookies = driver.get_cookies()
  21. with open('cookies.json', 'w') as f:
  22. json.dump(cookies, f)
  23. logging.info("Cookie获取完毕并已保存")
  24. def 加载cookie(driver, cookie_file='cookies.json'):
  25. # 从文件中加载cookies并添加到driver
  26. logging.info("开始加载cookie")
  27. with open(cookie_file, 'r') as f:
  28. cookies = json.load(f)
  29. for cookie in cookies:
  30. if 'expiry' in cookie:
  31. del cookie['expiry'] # 删除过期时间,避免格式错误
  32. driver.add_cookie(cookie)
  33. logging.info("Cookie加载完毕")
  34. def 安全获取文本(job, selector, default='未知'):
  35. """尝试从job对象中获取指定选择器的文本,如果失败则返回默认值"""
  36. try:
  37. return job.find(selector[0], class_=selector[1]).text.strip()
  38. except AttributeError:
  39. return default
  40. def 获取职位信息(driver, base_url, pages=1):
  41. logging.info("开始获取职位信息")
  42. 职位信息_list = []
  43. for i in range(1, pages + 1):
  44. url = f'{base_url}&page={i}'
  45. 加载成功 = False
  46. for 尝试次数 in range(3):
  47. try:
  48. driver.get(url)
  49. WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "job-card-wrapper")))
  50. 加载成功 = True
  51. break
  52. except Exception as e:
  53. logging.error(f"尝试 {尝试次数+1} 次访问 {url} 失败: {e}")
  54. time.sleep(5)
  55. if not 加载成功:
  56. logging.error(f"无法加载页面: {url}")
  57. continue
  58. soup = BeautifulSoup(driver.page_source, 'html.parser')
  59. jobs = soup.find_all('li', class_='job-card-wrapper')
  60. for job in jobs:
  61. # 获取每个职位的信息,并添加到列表中
  62. 职位名称 = 安全获取文本(job, ('span', 'job-name'))
  63. 工作地点 = 安全获取文本(job, ('span', 'job-area'))
  64. 薪资 = 安全获取文本(job, ('span', 'salary'), '面议')
  65. 标签列表 = [li.text for li in job.find('ul', class_='tag-list').find_all('li')]
  66. 经验要求 = 标签列表[0] if len(标签列表) > 0 else '未知'
  67. 教育要求 = 标签列表[1] if len(标签列表) > 1 else '未知'
  68. 联系人 = 安全获取文本(job, ('div', 'info-public'))
  69. 公司名称 = 安全获取文本(job, ('h3', 'company-name'))
  70. 公司标签列表 = [li.text for li in job.find('ul', class_='company-tag-list').find_all('li')]
  71. 公司类型 = 公司标签列表[0] if len(公司标签列表) > 0 else '未知'
  72. 公司规模 = 公司标签列表[1] if len(公司标签列表) > 1 else '未知'
  73. 详情 = ','.join([li.text for li in job.find('div', class_='job-card-footer').find('ul', class_='tag-list').find_all('li')])
  74. 职位详情链接 = "https://www.zhipin.com" + job.find('a')['href']
  75. # 直接将字典添加到列表中
  76. 职位信息_list.append({
  77. '职位名称': 职位名称,
  78. '工作地点': 工作地点,
  79. '薪资': 薪资,
  80. '经验要求': 经验要求,
  81. '教育要求': 教育要求,
  82. '联系人': 联系人,
  83. '公司名称': 公司名称,
  84. '公司类型': 公司类型,
  85. '公司规模': 公司规模,
  86. '详情': 详情,
  87. '职位详情链接': 职位详情链接
  88. })
  89. # 循环结束后,使用收集到的职位信息列表创建DataFrame
  90. 职位信息 = pd.DataFrame(职位信息_list)
  91. logging.info(f"获取到 {len(职位信息)} 个职位信息")
  92. return 职位信息
  93. if __name__ == '__main__':
  94. base_url = 'https://www.zhipin.com/web/geek/job?query=&city=101240100'
  95. data_file = '职位信息.csv' # 数据文件路径
  96. # 初始化webdriver,并设置Chrome Driver
  97. options = webdriver.ChromeOptions()
  98. try:
  99. driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
  100. driver.set_window_size(1920, 1080) # 调整为合适的大小
  101. except Exception as e:
  102. logging.error(f"创建WebDriver时出错: {e}")
  103. raise
  104. # 第一次运行时获取cookie,之后可以注释掉这行代码
  105. # 获取cookie(driver, 'https://www.zhipin.com')
  106. # 加载已有数据(如果文件存在)
  107. if os.path.exists(data_file):
  108. existing_data = pd.read_csv(data_file)
  109. else:
  110. existing_data = pd.DataFrame()
  111. try:
  112. # 加载cookie,必须先访问网站才能设置cookie
  113. driver.get("https://www.zhipin.com")
  114. 加载cookie(driver)
  115. # 获取职位信息,可以根据需要调整页数
  116. 新职位信息 = 获取职位信息(driver, base_url, pages=10)
  117. # 合并新旧数据,并去除重复项
  118. 更新后的职位信息 = pd.concat([existing_data, 新职位信息], ignore_index=True).drop_duplicates(subset=['职位名称', '公司名称'])
  119. except Exception as e:
  120. logging.error(f"获取职位信息时出错: {e}")
  121. driver.quit()
  122. raise
  123. # 输出或保存职位信息到CSV文件
  124. print(更新后的职位信息)
  125. 更新后的职位信息.to_csv(data_file, index=False, encoding='utf-8-sig')
  126. # 关闭driver
  127. driver.quit()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/808767
推荐阅读
相关标签
  

闽ICP备14008679号