首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何像翻书一样,稳定地抓到你想要的分页数据?

如何像翻书一样,稳定地抓到你想要的分页数据?

原创
作者头像
jackcode
发布2025-08-07 10:50:38
发布2025-08-07 10:50:38
16800
代码可运行
举报
文章被收录于专栏:爬虫资料爬虫资料
运行总次数:0
代码可运行
爬虫代理
爬虫代理

最近在做一些招聘市场的数据分析,碰到一个典型问题:分页数据抓不到头,还经常被限制请求。尤其像 51Job 这类网站,页面里几十条职位一页,你不翻页就只看到一角数据,翻太快又被挡。

后来我总结了一套思路,能稳定、低调地“翻完所有页”,还能直接把数据存进数据库做分析,效果还不错。想记录下来,一是备忘,二也分享给有同样需求的人。


为什么我在乎“分页”这事?

我们日常在网上看到的很多数据,比如职位列表、评论、产品、新闻,它们都是分页呈现的。看着一页页翻,其实背后服务器也是靠 URL 参数拼接出来的数据。

我之前抓 51Job 的“Python爬虫”相关职位,每次第一页能抓,第二页开始就不是很稳定,甚至偶尔封我 IP。所以,不但要能翻页,还得稳 —— 这就是重点了。


要做这个,我准备了什么?

1. 技术栈:

我这次用的是 Python,主要是这些库:

  • requests:发请求;
  • beautifulsoup4:解析网页;
  • sqlite3:写数据用的,内置,无需安装;
  • pandas:后面做点简单分析。

另外我还加了一层代理 —— 用的是一个爬虫代理服务,不然抓多了很容易被“注意”。


抓取的思路,其实就是“慢慢翻页,不惹事”

咱先说下分页 URL 的套路。51Job 的搜索 URL 其实是类似这样的:

代码语言:plain
复制
https://search.51job.com/list/000000,000000,0000,00,9,99,关键词,2,页码.html

这里的关键词可以换成 Python 爬虫(需要转义一下),页码是从 1 开始递增的。

所以我做的就是:

  1. 把关键词转成 URL 格式;
  2. 从第一页开始,一页页往下翻;
  3. 每一页都去解析里面的职位信息;
  4. 每翻一页就“等一会”,装得像正常人在看。

代码来了(我加了中文注释)

代码语言:python
代码运行次数:0
运行
复制
import requests
import sqlite3
import time
import random
from bs4 import BeautifulSoup
import pandas as pd
from urllib.parse import quote

# 设置代理信息(用的是亿牛云)
proxy_host = "proxy.16yun.cn"
proxy_port = "3100"
proxy_user = "16YUN"
proxy_pass = "16IP"

# 拼接代理字典
proxies = {
    "http": f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}",
    "https": f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}",
}

# 随机浏览器头,尽量别被识别成脚本
headers = {
    "User-Agent": random.choice([
        "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)"
    ])
}

# 搞个本地数据库来存
conn = sqlite3.connect("jobs_51job.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS jobs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT,
    company TEXT,
    location TEXT,
    salary TEXT,
    date TEXT,
    source_url TEXT
)
""")
conn.commit()

# 抓数据函数
def scrape_51job(keyword, max_pages=10):
    print(f"开始抓取关键词:{keyword}")
    for page in range(1, max_pages + 1):
        try:
            kw_encoded = quote(keyword)
            url = f"https://search.51job.com/list/000000,000000,0000,00,9,99,{kw_encoded},2,{page}.html"
            print(f"正在抓第 {page} 页:{url}")

            res = requests.get(url, headers=headers, proxies=proxies, timeout=10)
            res.encoding = 'gbk'  # 指定编码,不然会乱码
            soup = BeautifulSoup(res.text, "html.parser")
            jobs = soup.select("div#resultList div.el")[1:]  # 第一个是表头,跳过

            for job in jobs:
                title = job.select_one("p span a").get("title", "").strip()
                company = job.select_one("span.t2 a").get("title", "").strip()
                location = job.select_one("span.t3").text.strip()
                salary = job.select_one("span.t4").text.strip()
                date = job.select_one("span.t5").text.strip()
                link = job.select_one("p span a").get("href", "").strip()

                cursor.execute("""
                    INSERT INTO jobs (title, company, location, salary, date, source_url)
                    VALUES (?, ?, ?, ?, ?, ?)
                """, (title, company, location, salary, date, link))

            conn.commit()
            print(f"第 {page} 页 OK,共抓了 {len(jobs)} 条")
            time.sleep(random.uniform(1, 3))  # 随机等一下,低调点

        except Exception as e:
            print(f"第 {page} 页挂了:{e}")
            continue

# 数据分析函数:看看哪月招聘多
def analyze_jobs():
    df = pd.read_sql_query("SELECT * FROM jobs", conn)
    df["month"] = df["date"].apply(lambda x: "2025-" + x[:2] if "-" in x else "未知")
    stats = df.groupby("month").size().reset_index(name="job_count")
    stats = stats.sort_values(by="month")

    print("\n【每月职位数统计】")
    for _, row in stats.iterrows():
        print(f"{row['month']} 月份发布职位数量:{row['job_count']} 条")

# 主流程
if __name__ == "__main__":
    scrape_51job("Python 爬虫", max_pages=5)
    analyze_jobs()
    conn.close()

一些小经验

我抓的过程中,也踩了些坑,这里说下:

  • 编码问题:51Job 是 GBK 编码,不设置 res.encoding = 'gbk',中文就全花了。
  • 代理问题:代理不生效时,经常返回的是空页面或者重定向,一定要测试代理可用性。
  • 结构变了就得重新调:有一次页面结构更新了,原来 CSS 选择器就抓不到数据了,这种只能手动重新 F12 看一下。
  • 别太快了:有一回没加延迟,连抓 10 页直接就被封了 IP,加了代理和 sleep 才稳定下来。

写在最后

像这种分页抓数据的逻辑,其实大部分网站都差不多,你只要搞清楚分页 URL 的规律,再加上低调的抓法,就可以抓得很稳定。

我这次把数据存进 SQLite,是为了后面能做分析,比如看哪月招聘多,哪类岗位常见等。后续可以考虑导出 CSV、入库 MySQL、甚至做成一个可视化看板。

希望这篇小记对你有帮助。如果你也在爬分页,不妨试试看这种“翻书式”的思路!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么我在乎“分页”这事?
  • 要做这个,我准备了什么?
    • 1. 技术栈:
  • 抓取的思路,其实就是“慢慢翻页,不惹事”
  • 代码来了(我加了中文注释)
  • 一些小经验
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档