Python爬虫解决data-search-sol-meta属性token提取为None问题
问题根因
- 取值逻辑错误:目标token、jobId等数据存储在div标签的
data-search-sol-meta自定义属性中,并非标签包裹的内部文本。原代码使用.text.strip()取值,该div无可见内部文本,因此返回空值。 - 流程逻辑错误:分页爬取时
transform(c)写在for循环外部,仅会处理最后一页的返回内容;time.sleep(4)位置错误,无法在请求间生效防封禁效果。 - 反爬缺失:requests默认请求头特征明显,访问JobStreet时会被反爬策略拦截,返回不含职位数据的异常页面。
- 未做结构化转换:
data-search-sol-meta的属性值为JSON格式字符串,直接读取文本无法拆分出独立的token、jobId字段。
修正后可运行代码
import time import json import requests import pandas as pd from bs4 import BeautifulSoup # 浏览器请求头,伪装普通用户访问避免被反爬拦截 HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept-Language': 'en-MY,en;q=0.9' } joblist = [] def extract(page): url = f'https://www.jobstreet.com.my/en/job-search/administrative-assistant-jobs/{page}/' r = requests.get(url, headers=HEADERS) # 校验请求状态,遇到403/404等异常直接抛出,避免解析空页面 r.raise_for_status() soup = BeautifulSoup(r.content, 'html.parser') return soup def transform(soup): # 直接匹配带data-search-sol-meta属性的标签,无需硬编码动态生成的CSS类名,避免前端类名变更导致匹配失效 meta_tags = soup.find_all('div', attrs={'data-search-sol-meta': True}) for tag in meta_tags: # 核心修正:读取标签自定义属性值,而非读取标签内部文本 meta_str = tag.get('data-search-sol-meta') if not meta_str: continue # 解析JSON格式的元数据,拆分出需要的字段 meta_data = json.loads(meta_str) job_detail = { 'searchRequestToken': meta_data.get('searchRequestToken'), 'token': meta_data.get('token'), 'jobId': meta_data.get('jobId'), 'section': meta_data.get('section'), 'sectionRank': meta_data.get('sectionRank'), 'jobAdType': meta_data.get('jobAdType') } joblist.append(job_detail) if __name__ == '__main__': total_pages = 2 for page in range(1, total_pages + 1): print(f'Crawling Progress: [{page}/{total_pages}]') page_soup = extract(page) transform(page_soup) # 请求间隔放在每次请求完成后,控制访问频率避免被封禁 time.sleep(4) df = pd.DataFrame(joblist) # 测试打印结果前5行 print(df.head())
关键改动说明
- 取值逻辑修正:使用标签对象的
.get('属性名')方法读取自定义属性值,替换原代码读取内部文本的错误逻辑。 - 选择器优化:放弃硬编码编译生成的动态CSS类名,直接通过目标属性定位标签,适配站点前端迭代导致的类名变动。
- 流程逻辑修正:将页面解析、请求延迟逻辑移入分页循环内,保证每一页的职位数据都能被正常抓取处理。
- 反爬适配:添加真实浏览器请求头,增加请求状态校验,降低被反爬拦截的概率。
- 数据结构化:通过
json.loads()将属性值的JSON字符串解析为字典,直接提取目标字段,生成的DataFrame可直接用于后续分析,无需二次清洗。
内容的提问来源于stack exchange,提问作者kankerino
相关产品推荐
相关产品推荐

