【问题标题】:Web scraping bus schedules with Python使用 Python 抓取网络巴士时刻表
【发布时间】:2021-09-09 23:36:21
【问题描述】:

我想从以下网站https://ul.se 上抓取巴士时刻表时间。它是瑞典语的,但有一个英语选项,无论如何它不会影响我的主要问题。通过将我们感兴趣的位置放在搜索字段中,我们会到达以下链接,这是我感兴趣的示例。 https://www.ul.se/#/700600/0/Uppsala%20Centralstation%20(Uppsala)/700591/0/Stadsbiblioteket%20(Uppsala)//2/

通过右键单击并检查我想要抓取的元素,我可以在开发工具中看到它们,但在整个页面源中它没有列出。例如,通过复制我得到的选择器来查看下一班车的第一个可用时间

#travelResults > ul-search-journey-result-card:nth-child(3) > div > div.result-head > div.result-row.time > span.dpt-arr-time.ng-binding

这在我的代码中根本不起作用。即使我忘记了 BeautifulSoup(这是我正在尝试使用的)并且只是在完整的 html 中搜索任何指示时间的数字,仍然什么都没有。在整个来源中,似乎没有指示时间的数字。我错过了什么?怎么可能解决这个问题?任何帮助表示赞赏,我对这一切都很陌生。

【问题讨论】:

标签: python html web-scraping


【解决方案1】:

这个例子展示了如何使用json模块从json数据中解析路由:

import json
import requests


# url = "https://www.ul.se/#/700600/0/Uppsala%20Centralstation%20(Uppsala)/700591/0/Stadsbiblioteket%20(Uppsala)//2/"

api_url = "https://www.ul.se/api/journey/search"

params = {
    "changeTimeType": "0",
    "dateTime": "",
    "from": "Uppsala Centralstation (Uppsala)",  # <-- 1.
    "fromPointId": "700600",  # <-- 2.
    "fromPointType": "0",
    "maxWalkDistance": "3000",
    "priorityType": "0",
    "to": "Stadsbiblioteket (Uppsala)",  # <-- 3.
    "toPointId": "700591",  # <-- 4.
    "toPointType": "0",
    "trafficTypes": "1,2,3,4,5,6,7,8,9,10,11",
    "travelWhenType": "2",
    "via": "",
    "viaPointId": "",
    "walkSpeedType": "0",
}

data = requests.get(api_url, params=params).json()
data = json.loads(data["Payload"])

# uncomment to print all data:
# print(json.dumps(data, indent=4))

for journey in data:
    for route in journey["routeLinks"]:
        print(
            "{:<40} {:<30} {:<20} {:<20}".format(
                route["from"]["name"],
                route["to"]["name"],
                route["arrivalDateTime"],
                route["departureDateTime"],
            )
        )
    print()

打印:

Uppsala Centralstation (Uppsala)         Klostergatan (Uppsala)         2021-06-27T12:56:00  2021-06-27T12:55:00 
Klostergatan (Uppsala)                   Stadsbiblioteket (Uppsala)     2021-06-27T13:01:00  2021-06-27T12:56:00 

Uppsala Centralstation (Uppsala)         Klostergatan (Uppsala)         2021-06-27T13:02:00  2021-06-27T13:00:00 
Klostergatan (Uppsala)                   Stadsbiblioteket (Uppsala)     2021-06-27T13:07:00  2021-06-27T13:02:00 

Uppsala Centralstation (Uppsala)         Klostergatan (Uppsala)         2021-06-27T13:12:00  2021-06-27T13:10:00 
Klostergatan (Uppsala)                   Stadsbiblioteket (Uppsala)     2021-06-27T13:17:00  2021-06-27T13:12:00 

Uppsala Centralstation (Uppsala)         Stadsbiblioteket (Uppsala)     2021-06-27T13:20:00  2021-06-27T13:15:00 

Uppsala Centralstation (Uppsala)         Klostergatan (Uppsala)         2021-06-27T13:20:00  2021-06-27T13:18:00 
Klostergatan (Uppsala)                   Stadsbiblioteket (Uppsala)     2021-06-27T13:25:00  2021-06-27T13:20:00 

Uppsala Centralstation (Uppsala)         Klostergatan (Uppsala)         2021-06-27T13:21:00  2021-06-27T13:20:00 
Klostergatan (Uppsala)                   Stadsbiblioteket (Uppsala)     2021-06-27T13:26:00  2021-06-27T13:21:00 

【讨论】:

  • 非常感谢您提供涉及代码的答案!它帮助了很多像我这样的新手。这在我看来就像魔法一样,但我渴望学习。我在哪里可以找到有关如何自己执行此操作的信息?例如,您如何知道要使用哪个 api_url,使用 requests.get 调用中的参数等?有没有一些关于网页抓取的好系列教程可以推荐?
  • @Esoog 当你打开 Firefox 开发者工具 -> 网络选项卡(Chrome 也有类似的东西),你会看到页面正在执行的所有请求。当数据不在页面内时,页面必须将它们加载到某个地方......
【解决方案2】:

如果你解析复杂的json到达,你可以找到很多列

import requests
import pandas as pd

url = """https://www.ul.se/api/journey/search?changeTimeType=0&dateTime=&from=Uppsala+Centralstation+(Uppsala)&fromPointId=700600&fromPointType=0&maxWalkDistance=3000&priorityType=0&to=Stadsbiblioteket+(Uppsala)&toPointId=700591&toPointType=0&trafficTypes=1,2,3,4,5,6,7,8,9,10,11&travelWhenType=2&via=&viaPointId=&walkSpeedType=0"""


a = requests.get(url)
>>> pd.json_normalize(json.loads(json.loads(a.text)["Payload"])).columns
Index(['journeyKey', 'departureDateTime', 'departureIsTimingPoint',
       'hasRealTimeDepartureDeviation', 'realTimeDepartureDateTime',
       'arrivalDateTime', 'arrivalIsTimingPoint',
       'hasRealTimeArrivalDeviation', 'realTimeArrivalDateTime', 'travelTime',
       'routeLinks', 'priceZoneList', 'noOfChanges', 'zones', 'from.id',
       'from.name', 'from.area', 'from.type', 'from.coordinate.latitude',
       'from.coordinate.longitude', 'to.id', 'to.name', 'to.area', 'to.type',
       'to.coordinate.latitude', 'to.coordinate.longitude', 'ticketType.code',
       'ticketType.category', 'ticketType.name.parts',
       'ticketType.name.additions', 'ticketType.zones',
       'ticketType.validSeconds', 'ticketType.priceClasses',
       'ticketType.expires', 'ticketType.additionalTicketTypes'],
      dtype='object')

【讨论】:

    【解决方案3】:
    HTTP GET https://www.ul.se/api/journey/search?changeTimeType=0&dateTime=&from=Uppsala+Centralstation+(Uppsala)&fromPointId=700600&fromPointType=0&maxWalkDistance=3000&priorityType=0&to=Stadsbiblioteket+(Uppsala)&toPointId=700591&toPointType=0&trafficTypes=1,2,3,4,5,6,7,8,9,10,11&travelWhenType=2&via=&viaPointId=&walkSpeedType=0
    

    返回您要查找的数据。 (在浏览器中: F12 > Network > XHR )

    【讨论】:

      猜你喜欢
      • 2020-09-06
      • 1970-01-01
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      • 1970-01-01
      • 2023-02-07
      • 2021-08-11
      • 2020-09-04
      相关资源
      最近更新 更多