python实战-用海外代理IP抓LinkedIn热门岗位数据

最近我身边也有个小伙伴在做全球热门岗位趋势分析,想看看LinkedIn 上美国、德国这些国家都在招啥?技术岗多还是市场岗?到底啥技能最吃香?

传统找工作更多是"看到什么投什么",但如果你想系统地回答这些问题:

  • 哪些城市/国家,某个方向岗位最多?
  • Python / Go / 数据分析 / AI Agent 之类的技能,在哪些地区需求正在上升?
  • 远程岗位更集中在哪些时区?

就需要对岗位数据做更精细的采集与分析。

所以今天我们就实战一把:用 Python + 海外代理 IP,搞定 LinkedIn 热门岗位数据采集,并顺存成表格分析热门岗位与技能趋势。通过这种方式,我们可以从更广阔的视角洞察全球职场动态,从而提前布局。

1 为什么海外代理 IP 对求职洞察很重要?

类似我小伙伴一样,很多人打开LinkedIn准备大干一场的时候,立马踩坑:

一访问就跳登录页------同一IP频繁切换地址,网站做出的自我保护机制;

"怎么感觉国外也没那么多 Python 岗位啊?"------看到的是"本地化 + 个性化"的一小块视图,而不是不同地区的"原生视角";

访问频率一高就提示"请求异常"在同一IP下大量高频搜索,很快就会触发人机校验。

这时候,海外代理IP就变成一个绕不开的话题,海外代理IP允许分散请求,模拟自然用户行为;而且此类平台的供需也非常具有地区差异,例如北美岗位更注重科技技能,而欧洲可能强调可持续发展主题。使用海外代理可以访问特定地区的本地化数据,可以让我们更全面地触达这些需求。

2 准备工作

2.1 先装好环境,主角是 requests + BeautifulSoup

bash 复制代码
pip install requests beautifulsoup4 pandas

2.2 再准备一些代理 IP(可以临时拿测试 IP,看自己用的顺手的):

python 复制代码
# 功能:发送带青果网络海外代理IP的请求
def get_proxy():
proxy_url = "https://overseas.proxy.qg.net/get?key=yourkey&num=1&area=&isp=&format=txt&seq=\r\n&distinct=false" # 青果网络海外代理IP API地址"  

2.3 页面结构快速看一眼

随便搜一下 data analyst,跳转到这个 URL:

bash 复制代码
https://www.linkedin.com/jobs/search/?keywords=data%20analyst&location=United%20States&start=0

参数拆一下:

参数名 含义
keywords 搜索关键词(可 URL 编码)
location 地点,比如 United States
start 分页,从 0 开始,每页 25 条

这玩意就一"拼 URL 模板"的事儿,后续我们一页页改 start=25、50、75... 去翻页就行。

3 实战环节

3.1 初始化配置(关键词、页数、输出文件)

bash 复制代码
KEYWORD = "data analyst"
LOCATION = "United States"
PAGES = 3
OUTPUT = "linkedin_jobs.csv"

3.2 随机选择代理 + 请求头设置

python 复制代码
import random

def get_proxy():
    return random.choice(proxies_list)

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}

记得设置 UA,不然容易被判定成脚本行为。

3.3 主函数:爬取岗位数据

python 复制代码
import requests
from bs4 import BeautifulSoup
import pandas as pd
import random
import time
import os

# ========== 可配置区域 ==========
KEYWORD = "data analyst"
LOCATION = "United States"
PAGES = 5
OUTPUT_FILE = "linkedin_jobs_usa.csv"

# 带青果网络海外代理IP的请求
def get_proxy():
proxy_url = "https://overseas.proxy.qg.net/get?key=yourkey&num=1&area=&isp=&format=txt&seq=\r\n&distinct=false" # 青果网络海外代理IP API地址" 

USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
    "Mozilla/5.0 (X11; Linux x86_64)"
]

# ========== 工具函数 ==========
def get_proxy():
    return random.choice(proxies_list)

def get_headers():
    return {
        "User-Agent": random.choice(USER_AGENTS),
        "Accept-Language": "en-US,en;q=0.9"
    }

# ========== 主爬虫函数 ==========
def scrape_jobs(keyword, location, pages):
    results = []

    for page in range(pages):
        start = page * 25
        url = f"https://www.linkedin.com/jobs/search/?keywords={keyword}&location={location}&start={start}"
        print(f"\n➡️ 正在抓取第 {page + 1} 页: {url}")

        retry = 0
        while retry < 3:
            try:
                proxy = get_proxy()
                headers = get_headers()
                print(f"使用代理: {proxy['http']},UA: {headers['User-Agent']}")
                resp = requests.get(url, headers=headers, proxies=proxy, timeout=10)
                resp.raise_for_status()
                soup = BeautifulSoup(resp.text, "html.parser")
                jobs = soup.select("div.base-card")

                for job in jobs:
                    try:
                        title = job.select_one("h3").get_text(strip=True) if job.select_one("h3") else ""
                        company = job.select_one("h4").get_text(strip=True) if job.select_one("h4") else ""
                        location = job.select_one(".job-search-card__location").get_text(strip=True) if job.select_one(".job-search-card__location") else ""
                        link = job.select_one("a")["href"].split("?")[0] if job.select_one("a") else ""

                        results.append({
                            "Title": title,
                            "Company": company,
                            "Location": location,
                            "Link": link
                        })
                    except Exception as parse_err:
                        print("⚠️ 单条解析失败,已跳过")

                break  # 成功就跳出 retry
            except Exception as e:
                retry += 1
                wait = 2 ** retry
                print(f"❌ 抓取失败(第 {retry} 次):{e},{wait} 秒后重试...")
                time.sleep(wait)

        time.sleep(random.uniform(3, 6))

    return results

# ========== 启动爬虫 ==========
if __name__ == '__main__':
    data = scrape_jobs(KEYWORD, LOCATION, PAGES)
    df = pd.DataFrame(data)
    df.drop_duplicates(inplace=True)
    df.to_csv(OUTPUT_FILE, index=False)
    print(f"\n✅ 共抓取 {len(df)} 条岗位信息,保存到:{os.path.abspath(OUTPUT_FILE)}")

3.4 保存到 CSV

python 复制代码
import pandas as pd

data = scrape_jobs(KEYWORD, LOCATION, PAGES)
df = pd.DataFrame(data)
df.drop_duplicates(inplace=True)
df.to_csv(OUTPUT, index=False)
print(f"✅ 一共抓到 {len(df)} 条,已保存到 {OUTPUT}")

4 运行效果

运行后你会看到这样一批数据(CSV 可直接丢到 Excel 分析):

Title Company Location Link
Data Analyst Netflix California linkedin的链接1
BI Engineer Amazon New York linkedin的链接2

5 清洗数据

有了原始数据,并不代表你已经能直接分析了。通常还需要几步加工。

比如:岗位标题是个非常"自由"的字段:

  • Senior Python Developer
  • Python Engineer
  • Backend Engineer (Python)
  • Fullstack Developer (Python, React)

你如果直接按标题分组统计,会发现每个城市的"Top 岗位"都是一大堆看起来类似但名字不一样的东西。

所以我们可以将标题归一化:

  • 把标题转小写,去掉公司花字、标点;

  • 识别出核心词汇:python + developer/engineer/backend/fullstack

  • 映射到内部定义的"标准岗位族":

    • 全部归到 Python Backend Developer 或更粗粒度的 Python Developer

还可以根据地区、时间序列进行分析,技术需求是涨了还是少了,加入薪资、福利等字段,然后制作成图表。

6 写在最后

如果只从技术的角度看,python加上海外代理IP可以玩出很多花样,具体就要看整体的采集思路是否正确。而且优质的代理IP是根本,不然你代码写得再好看,没毛病,也是无法走通的。海外代理IP服务选择时,可以重点关注是否有合规说明,别用一办,直接跑路了,以及,国人的产品还是会比海外的好使一点,毕竟交流沟通无障碍,不然等老外那个时差邮件来回倒腾,黄花菜都凉了。

相关推荐
上进小菜猪2 小时前
把 KES 集群交给 Kubernetes 的九十天:一个 DBA 的试用实录
后端
两点王爷3 小时前
PostgreSQL 常用 SQL 语句与 GIS 相关函数详解
数据库·后端
麻雀飞吧3 小时前
先判断工具用来学习、开发还是执行
人工智能·python
考虑考虑4 小时前
Springboot环境变量占位符语法
spring boot·后端·spring
人邮异步社区4 小时前
学习Python的最佳学习路径是什么?
python·程序员
步行cgn5 小时前
Spring 基于 XML 的自动装配:byName 详解
java·后端·spring
troy1286 小时前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
jzshmyt6 小时前
我用 Python 从零“生成“了一个宇宙,然后让它观察自己(v14)
人工智能·pytorch·python·numpy·matplotlib·空间计算·scipy
RISCV_Explorer7 小时前
RISC-V启动与运行时规范机制解析——BRS约定、HSM多核启动与设备树要求
后端·risc-v
星栈独行7 小时前
ADK-Rust 是什么?Rust 生态新一代 AI Agent 开发套件
人工智能·后端·rust