抓取交互式网站

2024-05-13 19:23:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用Udacity中的学生数来取消课程名称,以找出哪些课程最受欢迎。我设法为项目创建代码:

import scrapy
class UdacityItem(scrapy.Item):
    name=scrapy.Field()
    users=scrapy.Field()

还有蜘蛛:

^{pr2}$

结果,我得到了课程的名称,但我得到的不是学生人数,而是“成千上万”。当我在浏览器中打开一个example website时,我看到“数千”是基值,稍后(在1-2秒内)此文本将变为一个正确的数字(我想得到它)。在

我的问题是:

  1. 为什么要进行这种替换?这是JavaScript代码吗?我会的 想了解这种变化的机制。在
  2. 我如何使用scrapy捕捉适当数量的学生?我希望这是可能的。在

提前感谢你的帮助。在


Tags: 项目代码nameimportfielditem学生class
1条回答
网友
1楼 · 发布于 2024-05-13 19:23:12

要获得注册计数,您必须模拟对特定课程id的https://www.udacity.com/api/summaries端点的API请求,该id可以从URL本身提取出来—例如,它是https://www.udacity.com/course/javascript-promises ud898URL的ud898。在

完整的卡盘:

import json

import re
from urllib import quote_plus

import scrapy


class UdacityItem(scrapy.Item):
    name = scrapy.Field()
    users = scrapy.Field()


class DmozSpider(scrapy.Spider):
    name = "UdSpider"
    allowed_domains = ["udacity.com"]
    start_urls = ["https://www.udacity.com/courses/all"]

    def parse(self, response):
        sites = response.xpath('//h3/a')
        for s in sites:
            t = UdacityItem()
            # name & url
            t['name'] = s.xpath('text()').extract()[0].strip()
            url = response.urljoin(s.xpath('@href').extract()[0])
            # request
            req = scrapy.Request(url, callback=self.second)
            req.meta['item'] = t
            # execute
            yield req

    def second(self, response):
        queries = [{
            "limit": 1,
            "model": "CourseStudentsSummary",
            "locator": {
                "sample_frequency": "daily",
                "content_context": [{
                    "node_key": re.search(r' (.*?)$', response.url).group(1)
                }]
            }
        }]
        yield scrapy.Request(method="GET",
                             url="https://www.udacity.com/api/summaries?queries=" + quote_plus(json.dumps(queries)),
                             callback=self.parse_totals)

    def parse_totals(self, response):
        print(json.loads(response.body[5:].strip())["summaries"]["default"][0]["data"]["total_enrollments"])

相关问题 更多 >