免费「python+pycharm」 链接:https://pan.quark.cn/s/48a86be2fdc0
在数据驱动的时代,招聘信息中隐藏着企业需求、行业趋势等宝贵信息。但直接爬取招聘网站常会遇到IP被封、反爬机制等阻碍。本文将通过实战案例,教你用Python+代理IP安全高效地采集数据,并提供完整的解决方案。
当你在凌晨3点用同一IP地址疯狂访问招聘网站时,系统会触发反爬机制:先弹出验证码,再返回403错误,最终直接封禁IP。这就像超市防损员盯着你反复清空货架——行为模式太异常。
代理IP的核心作用:
实测数据显示,使用代理IP可使爬虫存活时间提升15倍以上,数据获取量增加40%。
类型 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
免费代理 | 零成本 | 稳定性差、速度慢 | 测试验证阶段 |
数据中心IP | 速度快、价格低 | 容易被识别 | 大规模数据采集 |
住宅代理 | 模拟真实用户 | 成本较高 | 高反爬网站 |
移动代理 | 覆盖移动端数据 | 资源稀缺 | 移动端专项分析 |
推荐方案:
以站大爷IP代理为例,3分钟快速集成:
import requests
from fake_useragent import UserAgent
class ProxyHandler:
def __init__(self):
self.proxy_list = self.load_proxies() # 从站大爷API获取代理
self.ua = UserAgent()
def load_proxies(self):
# 实际开发中替换为你的代理API
return ["http://user:pass@ip:port", ...]
def get_proxy(self):
if not self.proxy_list:
raise Exception("代理池已耗尽")
return {"http": self.proxy_list.pop(0)}
def get_headers(self):
return {"User-Agent": self.ua.random}
以某招聘网站为例,演示完整采集流程:
https://www.example.com/jobs?page=1&keyword=python
import time
import random
from bs4 import BeautifulSoup
from proxy_handler import ProxyHandler
class JobSpider:
def __init__(self):
self.proxy = ProxyHandler()
self.base_url = "https://www.example.com/jobs"
self.keyword = "python"
self.results = []
def fetch_page(self, page_num):
url = f"{self.base_url}?page={page_num}&keyword={self.keyword}"
headers = self.proxy.get_headers()
proxy = self.proxy.get_proxy()
try:
response = requests.get(
url,
headers=headers,
proxies=proxy,
timeout=10
)
response.raise_for_status()
return response.text
except Exception as e:
print(f"请求失败: {e}")
# 失败后自动更换代理重试
return self.fetch_page(page_num)
def parse_job(self, html):
soup = BeautifulSoup(html, 'html.parser')
jobs = soup.select('.job-card') # 根据实际页面调整选择器
for job in jobs:
data = {
"title": job.select_one('.job-title').text.strip(),
"company": job.select_one('.company-name').text.strip(),
"salary": job.select_one('.salary').text.strip(),
"location": job.select_one('.job-location').text.strip()
}
self.results.append(data)
def run(self, max_pages=5):
for page in range(1, max_pages + 1):
print(f"正在采集第{page}页...")
html = self.fetch_page(page)
self.parse_job(html)
# 随机延迟1-3秒
time.sleep(random.uniform(1, 3))
# 每3页更换一次User-Agent
if page % 3 == 0:
self.proxy.ua = UserAgent()
if __name__ == "__main__":
spider = JobSpider()
spider.run(max_pages=10)
# 保存结果到CSV
import pandas as pd
df = pd.DataFrame(spider.results)
df.to_csv("jobs_data.csv", index=False, encoding='utf-8-sig')
当遇到更严格的反爬时,可采取以下策略:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def selenium_crawl(url):
options = Options()
options.add_argument('--headless')
options.add_argument(f'user-agent={proxy.ua.random}')
driver = webdriver.Chrome(options=options)
driver.get(url)
# 模拟鼠标移动
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.move_by_offset(100, 100).perform()
html = driver.page_source
driver.quit()
return html
策略类型 | 实现方式 | 效果 |
---|---|---|
随机轮换 | 每次请求随机选择代理 | 简单但可能重复 |
顺序轮换 | 按列表顺序依次使用 | 可预测性高 |
权重轮换 | 根据代理质量分配使用概率 | 平衡效率与稳定性 |
响应式轮换 | 失败时自动降级使用备用代理 | 最健壮的方案 |
推荐实现:
class SmartProxyPool:
def __init__(self):
self.primary_proxies = [...] # 优质代理
self.backup_proxies = [...] # 备用代理
def get_proxy(self):
if self.primary_proxies:
return {"http": self.primary_proxies.pop(0)}
elif self.backup_proxies:
print("警告:使用备用代理")
return {"http": self.backup_proxies.pop(0)}
else:
raise Exception("所有代理已耗尽")
import sqlite3
def save_to_db(data):
conn = sqlite3.connect('jobs.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS jobs (
title TEXT,
company TEXT,
salary TEXT,
location TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)
''')
for job in data:
cursor.execute('''
INSERT INTO jobs VALUES (?,?,?,?)
''', (job['title'], job['company'], job['salary'], job['location']))
conn.commit()
conn.close()
def clean_salary(salary_str):
try:
if "k" in salary_str.lower():
return float(salary_str.replace("k", "").replace("K", "")) * 1000
return float(salary_str)
except:
return None
# 应用清洗
df['salary_min'] = df['salary'].apply(
lambda x: clean_salary(x.split('-')[0]) if '-' in str(x) else clean_salary(x)
)
Q1:被网站封IP怎么办? A:立即启用备用代理池,建议使用住宅代理(如站大爷IP代理),配合每请求更换IP策略。更高级的方案是使用代理IP+Selenium模拟真实浏览器行为。
Q2:如何检测代理是否有效? A:实现代理测试函数:
def test_proxy(proxy):
test_url = "https://httpbin.org/ip"
try:
response = requests.get(test_url, proxies=proxy, timeout=5)
return "origin" in response.json()
except:
return False
Q3:招聘网站参数加密如何处理?
A:三种解决方案:
Q4:如何提高采集效率? A:
Q5:法律风险如何规避? A:
通过本文的代理IP+爬虫组合方案,可实现:
关键在于建立"代理池+行为模拟+异常处理"的三重防护体系。实际开发中建议先在小规模测试验证,再逐步扩大采集规模。记住:优秀的爬虫工程师,首先是合规的数据采集者。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。