You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy爬取Niche.com时href为#的学校链接无法跳转问题解决

解决Scrapy爬取Niche.com学校详情页的问题

遇到学校链接href为#的情况,本质是网站用JS动态控制跳转,真实链接通常藏在其他属性或页面内嵌的JSON数据里,下面是具体解决方案:

1. 定位真实详情页链接

检查自定义属性

大多数这类网站会把真实链接放在a标签的自定义属性里,比如data-url、data-href。打开开发者工具查看学校卡片的a标签,找到类似这样的结构:

<a href="#" data-url="/k12/wisconsin/abc-high-school">...</a>

直接提取data-url的值即可。

查找页面内嵌JSON数据

如果页面用React、Vue等框架渲染,真实数据通常会放在script标签里(比如id="__NEXT_DATA__"的标签),里面包含完整的学校列表和详情页URL。

抓包分析AJAX请求

滚动页面加载更多学校时,网站可能通过XHR请求获取分页数据,返回的JSON里会包含每个学校的详情链接。

2. Scrapy代码实现示例

列表页解析(提取真实链接)

import scrapy
import json

class NicheSchoolSpider(scrapy.Spider):
    name = 'niche_wi_schools'
    start_urls = ['https://www.niche.com/k12/search/best-schools/wisconsin/']

    def parse(self, response):
        # 方法1:提取自定义属性中的链接
        for school_card in response.css('div[class*="SchoolCard"]'):
            detail_path = school_card.css('a::attr(data-url)').get()
            if detail_path:
                detail_url = response.urljoin(detail_path)
                yield scrapy.Request(detail_url, callback=self.parse_detail)

        # 方法2:解析页面内嵌JSON(如果方法1无效时用)
        # script_content = response.css('script#__NEXT_DATA__::text').get()
        # if script_content:
        #     data = json.loads(script_content)
        #     schools = data['props']['pageProps']['searchResults']['items']
        #     for school in schools:
        #         detail_url = response.urljoin(school['url'])
        #         yield scrapy.Request(detail_url, callback=self.parse_detail)

        # 处理分页
        next_page = response.css('a.pagination__next::attr(href)').get()
        if next_page:
            yield scrapy.Request(response.urljoin(next_page), callback=self.parse)

    def parse_detail(self, response):
        # 提取学校详情信息,根据实际页面结构调整选择器
        yield {
            '学校名称': response.css('h1[class*="Heading__HeadingStyled"]::text').get(default='').strip(),
            '地址': response.css('div[class*="SchoolHeader__Address"]::text').get(default='').strip(),
            '电话': response.css('a[class*="SchoolHeader__PhoneLink"]::text').get(default='无'),
            '学费': response.css('div[class*="FactTable__Value"]:contains("Tuition")::text').get(default='').strip(),
            '招生人数': response.css('div[class*="FactTable__Value"]:contains("Enrollment")::text').get(default='').strip()
        }

3. 反爬注意事项

  • 设置合理的DOWNLOAD_DELAY(比如2-3秒),避免请求过于频繁
  • 在settings.py中配置真实的USER_AGENT,模拟浏览器请求
  • 若遇到验证码或IP封禁,可考虑使用代理IP池

内容的提问来源于stack exchange,提问作者Shivam Lanke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:01:33