【问题标题】:Scraping web data from JSON with python使用 python 从 JSON 中抓取 Web 数据
【发布时间】:2019-02-26 21:33:08
【问题描述】:

我想从this API 抓取时间表数据。返回的数据为 JSON 格式。我正在使用 python。

我试过以下代码:

snav_timetable_url = "https://booking.snav.it/api/v1/rates/1040/2019-02-25/1042/2019-02-25?lang=1"
fh = urllib.request.urlopen(snav_timetable_url)
snav_timetable = fh.read().decode('utf-8')
fh.close()
snav_timetable_data = json.loads(snav_timetable[len(snav_timetable)-2])
snav_timetable_data_cleaned = []
for departure in snav_timetable_data ['data']['ratesOutward']:
    snav_timetable_data_cleaned.append({
       'COMPANY': 'Snav',
       'CODICE CORSA': departure['coditinera'],
       'DEPARTURE DATE TIME': departure['strDatapart'],
       'ARRIVAL DATE TIME': departure['strDatarri']
    })

但出现错误

    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

我做错了什么?

【问题讨论】:

  • 请注意,您不是在“抓取”任何东西,这就是应该使用 json api 的方式。
  • 为什么要索引 JSON 字符串? snav_timetable[len(snav_timetable)-2] 不是有效的 JSON 文档,它是文档中的单个字符。只需解码整个字符串

标签: python json web-scraping


【解决方案1】:

你把 strDataarri 拼错了一个。

此外,requests 库可能会让这看起来更整洁。

import requests
snav_timetable_url = "https://booking.snav.it/api/v1/rates/1040/2019-02-25/1042/2019-02-25?lang=1"
r = requests.get(snav_timetable_url).json()

snav_timetable_data_cleaned = []
for departure in r['data']['ratesOutward']:
    snav_timetable_data_cleaned.append({
       'COMPANY': 'Snav',
       'CODICE CORSA': departure['coditinera'],
       'DEPARTURE DATE TIME': departure['strDatapart'],
       'ARRIVAL DATE TIME': departure['strDataarri']
    })

输出:

[{'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-25 08:25',
  'ARRIVAL DATE TIME': '2019-02-25 09:20'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-25 12:30',
  'ARRIVAL DATE TIME': '2019-02-25 13:25'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-25 16:20',
  'ARRIVAL DATE TIME': '2019-02-25 17:15'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-25 19:00',
  'ARRIVAL DATE TIME': '2019-02-25 19:55'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-26 08:25',
  'ARRIVAL DATE TIME': '2019-02-26 09:20'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-26 12:30',
  'ARRIVAL DATE TIME': '2019-02-26 13:25'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-26 16:20',
  'ARRIVAL DATE TIME': '2019-02-26 17:15'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-26 19:00',
  'ARRIVAL DATE TIME': '2019-02-26 19:55'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-27 08:25',
  'ARRIVAL DATE TIME': '2019-02-27 09:20'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-27 12:30',
  'ARRIVAL DATE TIME': '2019-02-27 13:25'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-27 16:20',
  'ARRIVAL DATE TIME': '2019-02-27 17:15'},
 {'COMPANY': 'Snav',
  'CODICE CORSA': 'NABECASA',
  'DEPARTURE DATE TIME': '2019-02-27 19:00',
  'ARRIVAL DATE TIME': '2019-02-27 19:55'}]

【讨论】:

    【解决方案2】:

    如果您使用的是 Python 3.x,最好使用 requests 库。以下是获取 json 响应的方法。

    import requests
    
    snav_timetable_url = "https://booking.snav.it/api/v1/rates/1040/2019-02-25/1042/2019-02-25?lang=1"
    fh = requests.get(snav_timetable_url)
    json_data = fh.json()
    

    这样您就不会出现任何错误,并且可以继续进行解析。

    for departure in json_data ['data']['ratesOutward']:
       snav_timetable_data_cleaned.append({
          'COMPANY': 'Snav',
          'CODICE CORSA': departure['coditinera'],
          'DEPARTURE DATE TIME': departure['strDatapart'],
          'ARRIVAL DATE TIME': departure['strDataarri']
       })
    

    【讨论】:

    • requests 有一个内置的 json 解析器,你的代码仍然会导致错误。
    • 我在发布之前运行了我的代码,它可以正常工作,没有任何错误。你能告诉我你遇到了什么错误吗?
    • 如果您也使用 Python 2.x,requests 是更好的库。并不是说您应该再将 Python 2.x 用于新项目。
    • 我以为你错过了原始评论中的 dataarri 拼写错误。
    【解决方案3】:

    您的错误在于尝试从响应中解码单个字符:

    >>> snav_timetable[len(snav_timetable)-2]
    '}'
    

    单个字符不是 JSON 文档,因此解析失败是理所当然的。您想解码整个响应

    snav_timetable_data = json.loads(snav_timetable)
    

    您可能希望在此处改用 requests library,它使 API 中的 loading JSON responses 变得微不足道:

    import requests
    
    snav_timetable_data = requests.get(snav_timetable_url).json()
    
    snav_timetable_data_cleaned = []
    for departure in snav_timetable_data['data']['ratesOutward']:
        snav_timetable_data_cleaned.append({
           'COMPANY': 'Snav',
           'CODICE CORSA': departure['coditinera'],
           'DEPARTURE DATE TIME': departure['strDatapart'],
           'ARRIVAL DATE TIME': departure['strDataarri']
        })
    

    请注意,我必须更正到达日期时间参考中的错字;这是strDataarri,而不是strDatarri

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      相关资源
      最近更新 更多