javascript - 使用scrapy抓取动态网页数据

标签 javascript python scrapy web-crawler

我正在尝试从 NBA 的官方统计数据中获取一些数据以用于某些数据分析。我使用 scrapy 作为我的主要抓取工具。然而,在检查网页元素后,我发现它是使用 javascript 动态生成的。我对 javascript 完全陌生,无法弄清楚它是如何工作的。(调用哪个 js 文件,它如何加载到其中包含数据表以及是否有更容易访问的方式来获取数据)我也有在网络中找到了一些 json 文件,我不知道它是如何使用的。

http://stats.nba.com/teamLineups.html?TeamID=1610612739&pageNo=1&rowsPerPage=100&Season=2008-09&sortField=MIN&sortOrder=DES&PerMode=Per48

任何人都可以指导我使用上面的 url 并告诉我网站实际如何运行以加载数据以及他们如何处理数据以便以这种方式显示?

关键的部分还是关于如何获取数据。我已经看到使用 POST 方法取回数据的答案(对不起,我什至不熟悉 GET/POST),但我仍然无法弄清楚它如何适用于这种情况。

感谢您的慷慨指导!

最佳答案

在此示例中,Javascript 仅允许在网页上发送、接收和显示内容,而无需为每个请求实际重新加载网页。 所以你不需要解析javascript,你只需要找到请求的信息,然后模仿那个请求,并解析响应。为此,您可以在 Firefox 中使用 Firebug,或在 Chrome 中使用开发人员工具(在 Windows 中为 ctrl+shift+J,在 Mac 中为 cmd+opt+J)。 在 Chrome 中,只需单击“网络”选项卡,您将在网站中单击时看到请求和响应。

在这个特定示例中,当您想要获取克利夫兰队“2008-09”的统计数据时,javascript 会发送多个请求。 您可能感兴趣的阵容要求是: http://stats.nba.com/stats/teamdashlineups?PlusMinus=N&pageNo=1&GroupQuantity=5&TeamID=1610612739&GameID=&Location=&SeasonType=Regular+Season&Season=2008-09&PaceAdjust=N&DateFrom=&sortOrder=DES&VsConference=&OpponentTeamID=0&DateTo=&GameSegment=&LastNGames=0&VsDivision=&LeagueID=00&Outcome=&GameScope=&MeasureType=Base&PerMode=Per48&sortField=MIN&SeasonSegment=&Period=0&Rank=N&Month=0&rowsPerPage=100

这是一个 scrapy base spider 的例子。您只需要定义 LineupItem,然后您可以使用 scrapy crawl stats -o output.json 执行它。

import json
from scrapy.spider import Spider
from scrapy.http import Request
from nba.items import LineupItem
from urllib import urlencode


class StatsSpider(Spider):
    name = "stats"
    allowed_domains = ["stats.nba.com"]
    start_urls = (
        'http://stats.nba.com/',
        )

    def parse(self, response):
        return self.get_lineup('1610612739','2008-09')

    def get_lineup(self, team_id, season):
        params = {
            'Season':         season,
            'SeasonType':     'Regular Season',
            'LeagueID':       '00',
            'TeamID':         team_id,
            'MeasureType':    'Base',
            'PerMode':        'Per48',
            'PlusMinus':      'N',
            'PaceAdjust':     'N',
            'Rank':           'N',
            'Outcome':        '',
            'Location':       '',
            'Month':          '0',
            'SeasonSegment':  '',
            'DateFrom':       '',
            'DateTo':         '',
            'OpponentTeamID': '0',
            'VsConference':   '',
            'VsDivision':     '',
            'GameSegment':    '',
            'Period':         '0',
            'LastNGames':     '0',
            'GroupQuantity':  '5',
            'GameScope':      '',
            'GameID':         '',
            'pageNo':         '1',
            'rowsPerPage':    '100',
            'sortField':      'MIN',
            'sortOrder':      'DES'
        }
        return Request(
            url="http://stats.nba.com/stats/teamdashlineups?" + urlencode(params),
            dont_filter=True,
            callback=self.parse_lineup
        )

    def parse_lineup(self,response):
        data = json.loads(response.body)
        for lineup in data['resultSets'][1]['rowSet']:
            item = LineupItem()
            item['group_set'] = lineup[0]
            item['group_id'] = lineup[1]
            item['group_name'] = lineup[2]
            item['gp'] = lineup[3]
            item['w'] = lineup[4]
            item['l'] = lineup[5]
            item['w_pct'] = lineup[6]
            item['min'] = lineup[7]
            item['fgm'] = lineup[8]
            item['fga'] = lineup[9]
            item['fg_pct'] = lineup[10]
            item['fg3m'] = lineup[11]
            item['fg3a'] = lineup[12]
            item['fg3_pct'] = lineup[13]
            item['ftm'] = lineup[14]
            item['fta'] = lineup[15]
            item['ft_pct'] = lineup[16]
            item['oreb'] = lineup[17]
            item['dreb'] = lineup[18]
            item['reb'] = lineup[19]
            item['ast'] = lineup[20]
            item['tov'] = lineup[21]
            item['stl'] = lineup[22]
            item['blk'] = lineup[23]
            item['blka'] = lineup[24]
            item['pf'] = lineup[25]
            item['pfd'] = lineup[26]
            item['pts'] = lineup[27]
            item['plus_minus'] = lineup[28]
            yield item

这将导致像这样的 json 记录:

{"gp": 30, "fg_pct": 0.491, "group_name": "Ilgauskas,Zydrunas - James,LeBron - Wallace,Ben - West,Delonte - Williams,Mo", "group_set": "Lineups", "w_pct": 0.833, "pts": 103.0, "min": 484.9866666666667, "tov": 13.3, "fta": 21.6, "pf": 16.0, "blk": 7.7, "reb": 44.2, "blka": 3.0, "ftm": 16.6, "ft_pct": 0.771, "fg3a": 18.7, "pfd": 17.2, "ast": 23.3, "fg3m": 7.4, "fgm": 39.5, "fg3_pct": 0.397, "dreb": 32.0, "fga": 80.4, "plus_minus": 18.4, "stl": 8.3, "l": 5, "oreb": 12.3, "w": 25, "group_id": "980 - 2544 - 1112 - 2753 - 2590"}

关于javascript - 使用scrapy抓取动态网页数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24709635/

相关文章:

python - Scrapy Xpath : Extracting @title from img node

javascript - 如何在JS中使用ajax请求的结果?

javascript - 如何在 Django 模板中连接内容 block ?

python - 为什么我的 2D fft 中会出现几行零?

python - PyQt QtCharts 设计器插件

python - TensorFlow 的 ./configure 在哪里以及如何启用 GPU 支持?

javascript - 单击编辑按钮后显示更新和取消按钮

javascript - SoundCloud API 给出 ​​ "Uncaught SyntaxError: Unexpected token : "错误

python-2.7 - python.failure.Failure OpenSSL.SSL.Scrapy 中的错误(版本 1.0.4)

python - 当 xhr 响应不可读时如何抓取无限滚动页面?