運(yùn)行環(huán)境要求
- 操作系統(tǒng):適用于Windows、macOS、Linux。
- Python版本:Python 3.6及以上。
-
依賴庫(kù):
- selenium:用于模擬瀏覽器操作。
- webdriver_manager:自動(dòng)管理驅(qū)動(dòng)程序。
- BeautifulSoup4:解析HTML頁(yè)面。
- pandas:數(shù)據(jù)處理和CSV文件操作。
- logging:日志記錄。
pip install selenium webdriver_manager beautifulsoup4 pandas
設(shè)計(jì)思路
本項(xiàng)目旨在通過(guò)Selenium模擬用戶瀏覽器行為,獲取特定網(wǎng)站(如Boss直聘)上的職位信息,并利用BeautifulSoup解析這些信息。為了實(shí)現(xiàn)數(shù)據(jù)的持續(xù)累積而不是每次運(yùn)行都覆蓋原有數(shù)據(jù),采用pandas進(jìn)行數(shù)據(jù)合并和去重,最終將更新后的數(shù)據(jù)保存到CSV文件中。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-859556.html
具體實(shí)踐
-
初始化Selenium WebDriver:配置ChromeDriver,啟動(dòng)Chrome瀏覽器實(shí)例。
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager options = webdriver.ChromeOptions() try: driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) except Exception as e: logging.error(f"創(chuàng)建WebDriver時(shí)出錯(cuò): {e}") raise
-
獲取并保存Cookies:訪問目標(biāo)網(wǎng)站并手動(dòng)登錄,然后保存Cookies以便后續(xù)自動(dòng)登錄使用。
def 獲取cookie(driver, url): logging.info("開始獲取cookie") driver.get(url) time.sleep(30) # 等待足夠的時(shí)間手動(dòng)登錄并保存cookies cookies = driver.get_cookies() with open('cookies.json', 'w') as f: json.dump(cookies, f) logging.info("Cookie獲取完畢并已保存")
-
加載Cookies實(shí)現(xiàn)自動(dòng)登錄:在后續(xù)的會(huì)話中加載之前保存的Cookies,實(shí)現(xiàn)自動(dòng)登錄。
def 加載cookie(driver, cookie_file='cookies.json'): logging.info("開始加載cookie") with open(cookie_file, 'r') as f: cookies = json.load(f) for cookie in cookies: if 'expiry' in cookie: del cookie['expiry'] # 刪除過(guò)期時(shí)間,避免格式錯(cuò)誤 driver.add_cookie(cookie) logging.info("Cookie加載完畢")
-
爬取職位信息:訪問職位列表頁(yè)面,使用BeautifulSoup解析頁(yè)面,提取職位相關(guān)信息。
from bs4 import BeautifulSoup from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By def 獲取職位信息(driver, base_url, pages=1): logging.info("開始獲取職位信息") 職位信息_list = [] for i in range(1, pages + 1): url = f'{base_url}&page={i}' driver.get(url) WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "job-card-wrapper"))) soup = BeautifulSoup(driver.page_source, 'html.parser') jobs = soup.find_all('li', class_='job-card-wrapper') # 提取并添加職位信息到列表中... return pd.DataFrame(職位信息_list)
-
數(shù)據(jù)去重與累積:讀取已有的數(shù)據(jù)文件(如果存在),將新抓取的數(shù)據(jù)與舊數(shù)據(jù)合并,去除重復(fù)項(xiàng),然后保存更新后的數(shù)據(jù)。
import pandas as pd if os.path.exists(data_file): existing_data = pd.read_csv(data_file) else: existing_data = pd.DataFrame() 新職位信息 = 獲取職位信息(driver, base_url, pages=5) 更新后的職位信息 = pd.concat([existing_data, 新職位信息], ignore_index=True).drop_duplicates(subset=['職位名稱', '公司名稱']) 更新后的職位信息.to_csv(data_file, index=False, encoding='utf-8-sig')
技術(shù)要點(diǎn)
- Selenium的高級(jí)應(yīng)用:包括但不限于Cookies的處理、顯式等待(WebDriverWait)等技巧,以確保頁(yè)面加載完成并成功獲取數(shù)據(jù)。
- BeautifulSoup的靈活運(yùn)用:精確地定位和提取所需的HTML元素。
- Pandas的數(shù)據(jù)處理能力:有效地合并、去重和保存數(shù)據(jù)。
項(xiàng)目復(fù)盤
-
挑戰(zhàn):
- 頁(yè)面結(jié)構(gòu)變化導(dǎo)致的數(shù)據(jù)提取失敗。
- 網(wǎng)站反爬蟲機(jī)制的應(yīng)對(duì)。
- 數(shù)據(jù)去重邏輯的設(shè)計(jì)。
-
解決方案:
- 定期檢查目標(biāo)網(wǎng)站的頁(yè)面結(jié)構(gòu),及時(shí)更新選擇器。
- 合理設(shè)置請(qǐng)求間隔,使用Cookies模擬登錄狀態(tài),減少被封概率。
- 利用pandas強(qiáng)大的數(shù)據(jù)處理功能,根據(jù)特定字段進(jìn)行去重。
?完整源碼
import logging
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
import pandas as pd
import os
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import json
# 設(shè)置日志記錄
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def 獲取cookie(driver, url):
# 訪問指定的URL并等待用戶手動(dòng)登錄,然后保存cookies
logging.info("開始獲取cookie")
driver.get(url)
time.sleep(30) # 等待足夠的時(shí)間手動(dòng)登錄并保存cookies
cookies = driver.get_cookies()
with open('cookies.json', 'w') as f:
json.dump(cookies, f)
logging.info("Cookie獲取完畢并已保存")
def 加載cookie(driver, cookie_file='cookies.json'):
# 從文件中加載cookies并添加到driver
logging.info("開始加載cookie")
with open(cookie_file, 'r') as f:
cookies = json.load(f)
for cookie in cookies:
if 'expiry' in cookie:
del cookie['expiry'] # 刪除過(guò)期時(shí)間,避免格式錯(cuò)誤
driver.add_cookie(cookie)
logging.info("Cookie加載完畢")
def 安全獲取文本(job, selector, default='未知'):
"""嘗試從job對(duì)象中獲取指定選擇器的文本,如果失敗則返回默認(rèn)值"""
try:
return job.find(selector[0], class_=selector[1]).text.strip()
except AttributeError:
return default
def 獲取職位信息(driver, base_url, pages=1):
logging.info("開始獲取職位信息")
職位信息_list = []
for i in range(1, pages + 1):
url = f'{base_url}&page={i}'
加載成功 = False
for 嘗試次數(shù) in range(3):
try:
driver.get(url)
WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "job-card-wrapper")))
加載成功 = True
break
except Exception as e:
logging.error(f"嘗試 {嘗試次數(shù)+1} 次訪問 {url} 失敗: {e}")
time.sleep(5)
if not 加載成功:
logging.error(f"無(wú)法加載頁(yè)面: {url}")
continue
soup = BeautifulSoup(driver.page_source, 'html.parser')
jobs = soup.find_all('li', class_='job-card-wrapper')
for job in jobs:
# 獲取每個(gè)職位的信息,并添加到列表中
職位名稱 = 安全獲取文本(job, ('span', 'job-name'))
工作地點(diǎn) = 安全獲取文本(job, ('span', 'job-area'))
薪資 = 安全獲取文本(job, ('span', 'salary'), '面議')
標(biāo)簽列表 = [li.text for li in job.find('ul', class_='tag-list').find_all('li')]
經(jīng)驗(yàn)要求 = 標(biāo)簽列表[0] if len(標(biāo)簽列表) > 0 else '未知'
教育要求 = 標(biāo)簽列表[1] if len(標(biāo)簽列表) > 1 else '未知'
聯(lián)系人 = 安全獲取文本(job, ('div', 'info-public'))
公司名稱 = 安全獲取文本(job, ('h3', 'company-name'))
公司標(biāo)簽列表 = [li.text for li in job.find('ul', class_='company-tag-list').find_all('li')]
公司類型 = 公司標(biāo)簽列表[0] if len(公司標(biāo)簽列表) > 0 else '未知'
公司規(guī)模 = 公司標(biāo)簽列表[1] if len(公司標(biāo)簽列表) > 1 else '未知'
詳情 = ','.join([li.text for li in job.find('div', class_='job-card-footer').find('ul', class_='tag-list').find_all('li')])
職位詳情鏈接 = "https://www.zhipin.com" + job.find('a')['href']
# 直接將字典添加到列表中
職位信息_list.append({
'職位名稱': 職位名稱,
'工作地點(diǎn)': 工作地點(diǎn),
'薪資': 薪資,
'經(jīng)驗(yàn)要求': 經(jīng)驗(yàn)要求,
'教育要求': 教育要求,
'聯(lián)系人': 聯(lián)系人,
'公司名稱': 公司名稱,
'公司類型': 公司類型,
'公司規(guī)模': 公司規(guī)模,
'詳情': 詳情,
'職位詳情鏈接': 職位詳情鏈接
})
# 循環(huán)結(jié)束后,使用收集到的職位信息列表創(chuàng)建DataFrame
職位信息 = pd.DataFrame(職位信息_list)
logging.info(f"獲取到 {len(職位信息)} 個(gè)職位信息")
return 職位信息
if __name__ == '__main__':
base_url = 'https://www.zhipin.com/web/geek/job?query=&city=101240100'
data_file = '職位信息.csv' # 數(shù)據(jù)文件路徑
# 初始化webdriver,并設(shè)置Chrome Driver
options = webdriver.ChromeOptions()
try:
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
driver.set_window_size(1920, 1080) # 調(diào)整為合適的大小
except Exception as e:
logging.error(f"創(chuàng)建WebDriver時(shí)出錯(cuò): {e}")
raise
# 第一次運(yùn)行時(shí)獲取cookie,之后可以注釋掉這行代碼
# 獲取cookie(driver, 'https://www.zhipin.com')
# 加載已有數(shù)據(jù)(如果文件存在)
if os.path.exists(data_file):
existing_data = pd.read_csv(data_file)
else:
existing_data = pd.DataFrame()
try:
# 加載cookie,必須先訪問網(wǎng)站才能設(shè)置cookie
driver.get("https://www.zhipin.com")
加載cookie(driver)
# 獲取職位信息,可以根據(jù)需要調(diào)整頁(yè)數(shù)
新職位信息 = 獲取職位信息(driver, base_url, pages=10)
# 合并新舊數(shù)據(jù),并去除重復(fù)項(xiàng)
更新后的職位信息 = pd.concat([existing_data, 新職位信息], ignore_index=True).drop_duplicates(subset=['職位名稱', '公司名稱'])
except Exception as e:
logging.error(f"獲取職位信息時(shí)出錯(cuò): {e}")
driver.quit()
raise
# 輸出或保存職位信息到CSV文件
print(更新后的職位信息)
更新后的職位信息.to_csv(data_file, index=False, encoding='utf-8-sig')
# 關(guān)閉driver
driver.quit()
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-859556.html
到了這里,關(guān)于Python實(shí)戰(zhàn):使用selenium及BeautifulSoup4進(jìn)行BOOS直聘信息爬取與數(shù)據(jù)累積【附源碼】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!