基于urllib+requests库+伪装浏览器实现爬取国内招聘网站并保存csv文件的爬虫
以下是一个基于urllib和requests库,通过伪装浏览器请求头来爬取国内招聘网站(以智联招聘为例)上海地区与机器学习相关的招聘信息,并将结果保存到CSV文件的完整实现方案。
设计思路
- 目标分析:确定要爬取的招聘网站(智联招聘)、目标地区(上海)和关键词(机器学习)
- 请求伪装:设置合理的User-Agent等请求头信息模拟浏览器访问
- 分页处理:实现多页爬取以获取足够数量的招聘信息
- 数据解析:使用正则表达式或解析库提取关键信息(职位名称、公司、薪资等)
- 数据存储:将结构化数据保存到CSV文件
- 异常处理:添加适当的异常处理机制保证爬虫稳定性
核心代码实现
# -*- coding: utf-8 -*-import reimport csvimport requestsfrom urllib.parse import urlencodefrom requests.exceptions import RequestExceptionfrom datetime import datetimedef get_one_page(city, keyword, page): """ 获取单页HTML内容 :param city: 城市 :param keyword: 搜索关键词 :param page: 页码 :return: HTML文本或None """ try: params = { 'jl': city, # 城市 'kw': keyword, # 关键词 'p': page, # 页码 'isadv': 0, 'isfilter': 1, 'sg': 'd5289e6c1a1249e9b6ae56066007107e', # 防爬参数 'st': '-1', # 排序方式 'kt': '3' # 未知参数 } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Referer': 'https://www.zhaopin.com/'
, 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' } url = 'https://sou.zhaopin.com/?'
+ urlencode(params) response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() response.encoding = 'utf-8' return response.text except RequestException as e: print(f"请求失败: {e}") return Nonedef parse_one_page(html): """ 解析单页HTML内容 :param html: HTML文本 :return: 生成器, yield招聘信息字典 """ try: # 使用正则表达式匹配职位信息 pattern = re.compile( r'<div class="jobinfo__name".*?<a.*?>(.*?)</a>.*?' # 职位名称 r'<div class="companyinfo__name".*?<a.*?>(.*?)</a>.*?' # 公司名称 r'<p class="jobinfo__salary".*?>(.*?)</p>.*?' # 薪资 r'<span class="jobinfo__other-info-item".*?>(.*?)</span>.*?' # 地区 r'<span class="jobinfo__other-info-item".*?>(.*?)</span>', # 经验要求 re.S ) items = re.findall(pattern, html) for item in items: yield { '职位名称': item[0].strip(), '公司名称': item[1].strip(), '薪资': item[2].strip(), '地区': item[3].strip(), '经验要求': item[4].strip(), '爬取时间': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } except Exception as e: print(f"解析失败: {e}")def save_to_csv(data, filename): """ 保存数据到CSV文件 :param data: 数据列表 :param filename: 文件名 """ if not data: return headers = list(data[0].keys()) try: with open(filename, 'a', newline='', encoding='utf-8-sig') as f: writer = csv.DictWriter(f, fieldnames=headers) # 如果是新文件,写入表头 if f.tell() == 0: writer.writeheader() writer.writerows(data) print(f"成功保存 {len(data)} 条数据到 {filename}") except Exception as e: print(f"保存文件失败: {e}")def main(city, keyword, max_pages): """ 主函数 :param city: 城市 :param keyword: 关键词 :param max_pages: 最大爬取页数 """ filename = f"{city}_{keyword}_jobs_{datetime.now().strftime('%Y%m%d')}.csv" for page in range(1, max_pages + 1): print(f"正在爬取第 {page} 页...") html = get_one_page(city, keyword, page) if not html: continue jobs = list(parse_one_page(html)) if not jobs: print("未找到更多职位信息,可能已到达最后一页") break save_to_csv(jobs, filename)if __name__ == '__main__': # 示例:爬取上海地区机器学习相关职位,最多爬取5页 main('上海', '机器学习', 5)代码说明
请求伪装:
设置了完整的请求头信息,包括User-Agent、Referer等
添加了必要的查询参数(如sg、st等)以提高请求成功率
数据解析:
使用正则表达式匹配职位关键信息
提取了职位名称、公司名称、薪资、地区和经验要求等字段
添加了爬取时间戳便于后续分析
异常处理:
对网络请求添加了try-catch块
对文件操作进行了异常捕获
使用response.raise_for_status()检查HTTP状态
数据存储:
使用utf-8-sig编码确保中文正常显示
自动判断是否需要写入表头
按日期生成文件名避免覆盖
扩展建议
反爬策略:
添加随机延迟避免请求过于频繁
使用代理IP池应对IP限制
实现更复杂的请求头轮换
功能增强:
添加多线程/异步请求提高效率
实现增量爬取(只爬取新职位)
添加数据清洗和去重功能
合规性:
遵守robots.txt规则
设置合理的爬取频率
考虑使用官方API(如果有)
这个实现提供了完整的爬虫流程,可以根据实际需求调整参数和解析规则。注意在实际使用时应该遵守目标网站的使用条款,合理控制爬取频率。