正如 Tim Roberts 所指出的,您尝试从中抓取的页面的实际 HTML 文档只是一个空模板。稍后使用 JavaScript 异步填充 DOM。在这种情况下,当单击 Rankings Indicator 选项卡时,JavaScript 会向 API 发出 XHR HTTP GET 请求,其响应是 JSON 并包含您要查找的信息。你只需要模仿那个请求。
在这种情况下,JSON 的某些部分恰好包含 HTML,您可以使用 BeautifulSoup 对其进行解析。
def get_entries():
import requests
url = "https://www.topuniversities.com/sites/default/files/qs-rankings-data/en/3740566_indicators.txt?1637817445?v=1637823042256"
headers = {
"user-agent": "Mozilla/5.0",
"x-requested-with": "XMLHttpRequest"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
def make_pretty(entry):
from bs4 import BeautifulSoup as Soup
return {
"name": Soup(entry["uni"], "html.parser").select_one(".uni-link").get_text(strip=True),
"rank": entry["overall_rank"],
"reputation": Soup(entry["ind_76"], "html.parser").select_one(".td-wrap-in").get_text(strip=True)
}
yield from map(make_pretty, response.json()["data"])
def main():
from itertools import islice
for entry in islice(get_entries(), 5):
print(entry)
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
输出:
{'name': 'Massachusetts Institute of Technology (MIT)', 'rank': '1', 'reputation': '100'}
{'name': 'University of Oxford', 'rank': '2', 'reputation': '100'}
{'name': 'Stanford University', 'rank': '3', 'reputation': '100'}
{'name': 'University of Cambridge', 'rank': '4', 'reputation': '100'}
{'name': 'Harvard University', 'rank': '5', 'reputation': '100'}
在本例中,我只打印前五个条目。要打印所有 1300 个条目,只需将 main 更改为:
def main():
for entry in get_entries():
print(entry)
return 0