无法抓取Indeed/LinkedIn数据:403错误及元素定位问题求助
问题解决指南:爬虫403拦截与元素定位失败
一、403响应问题(Indeed/LinkedIn职位页面)
原因
Indeed和LinkedIn的职位页面都有严格的反爬机制,直接用requests请求会被识别为爬虫:
- 请求头信息不足或UA版本过旧(你使用的Chrome 77版本太老,易被检测)
- 缺少会话维持(未处理Cookie)
- 请求频率过高,触发IP限制
- LinkedIn还会检测浏览器指纹,普通Selenium易被识别
解决方案
更新请求头并使用Session维持会话
补充必要的请求头字段,用requests.Session()自动处理Cookie,模拟真实用户会话:import requests session = requests.Session() headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Referer": "https://www.indeed.co.in/", "Connection": "keep-alive" } session.headers.update(headers)控制请求频率
每次请求后加入2-5秒延迟,避免触发频率限制:import time time.sleep(3)针对LinkedIn:使用指纹绕过工具
普通Selenium易被检测,改用undetected-chromedriver或Playwright,绕过浏览器指纹验证。
二、元素定位失败问题
原因
- 页面内容动态渲染:
requests获取的静态HTML中不存在目标元素(比如Indeed的职位卡片由JS加载) - 元素的class/id动态生成:Indeed/LinkedIn会随机更新元素标识,依赖固定id/class定位会失效
- 内容嵌套在iframe中:部分页面内容需切换iframe才能访问
解决方案
处理动态渲染页面
改用支持JS渲染的工具(如Playwright、undetected-chromedriver),替代requests+BeautifulSoup。使用稳定选择器
避免依赖易变的class/id,优先选择:data-testid属性(网站用于测试的标识,通常不会频繁变更)- 标签结构+文本特征
- CSS选择器(如
div[data-testid="mosaic-jobResults"])
修正代码中的空值判断
你当前代码中outer_most_point可能为None(因为403返回的页面没有目标元素),导致调用find('ul')触发AttributeError。需先判断元素是否存在:outer_most_point = soup.find('div', attrs={'id': 'mosaic-provider-jobcards'}) if outer_most_point: ul_element = outer_most_point.find('ul') if ul_element: for i in ul_element: # 处理逻辑 pass else: print("目标容器未找到,检查页面结构或反爬状态")
修正后的完整示例(Indeed爬虫)
import requests from bs4 import BeautifulSoup import time import pandas as pd session = requests.Session() headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Referer": "https://www.indeed.co.in/", "Connection": "keep-alive" } session.headers.update(headers) skill = input('Enter your Skill: ').strip() place = input('Enter the location: ').strip() no_of_pages = int(input('Enter the # of pages to scrape: ')) job_data = [] for page in range(no_of_pages): # 编码特殊字符,避免URL错误 url = f'https://www.indeed.co.in/jobs?q={requests.utils.quote(skill)}&l={requests.utils.quote(place)}&sort=date&start={page * 10}' try: response = session.get(url) response.raise_for_status() print(f"Page {page+1} Status: {response.status_code}") soup = BeautifulSoup(response.text, 'lxml') # 使用稳定的选择器定位职位容器 job_container = soup.find('div', {'data-testid': 'mosaic-jobResults'}) or soup.find('div', class_='jobsearch-JobSearchResults') if job_container: job_cards = job_container.find_all('div', class_='job_seen_beacon') for card in job_cards: title = card.find('h2').get_text(strip=True) if card.find('h2') else 'N/A' company = card.find('span', class_='companyName').get_text(strip=True) if card.find('span', class_='companyName') else 'N/A' location = card.find('div', class_='companyLocation').get_text(strip=True) if card.find('div', class_='companyLocation') else 'N/A' job_data.append({"Title": title, "Company": company, "Location": location}) else: print(f"Page {page+1}: 未找到职位容器,可能页面结构变更或被反爬拦截") time.sleep(3) except requests.exceptions.HTTPError as e: print(f"Page {page+1} HTTP错误: {e}") except Exception as e: print(f"Page {page+1} 错误: {e}") # 保存数据到CSV pd.DataFrame(job_data).to_csv('indeed_jobs.csv', index=False) print(f"抓取完成,共{len(job_data)}条职位数据")
内容的提问来源于stack exchange,提问作者KRISHNANDU RANJN ROY
相关产品推荐
相关产品推荐

