【问题标题】:I'm trying to scrape QS world university rankings with Python我正在尝试用 Python 抓取 QS 世界大学排名
【发布时间】:2022-01-03 11:18:15
【问题描述】:

我正在尝试从 QS 排名网站中提取大学名称、排名和学术声誉。 (地址如下)“学术声誉”数据位于“排名指标”选项卡中。

“https://www.topuniversities.com/university-rankings/world-university-rankings/2022”

首先我尝试使用 Python 获取大学名称,但没有成功。这段代码似乎提供了很多“a”标签数据,但我无法使用“uni-link”类获取大学名称。

有人可以帮我改进我的代码吗?

from bs4 import BeautifulSoup
import requests

url="https://www.topuniversities.com/university-rankings/world-university-rankings/2022"
response=requests.get(url)

html = response.text
soup = BeautifulSoup(html, 'html.parser')

uni= soup.find_all('a', class_="uni-link")
for item in uni:
    print(item.text)

【问题讨论】:

  • 您查看过该网站的代码吗?您获取的 HTML 不包含任何大学数据。该网站全部使用 Javascript 动态构建。您将不得不使用 Selenium 之类的东西来运行浏览器来解释 Javascript。

标签: python beautifulsoup


【解决方案1】:

正如 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

【讨论】:

  • 哇!我已经为此苦苦挣扎了一个星期,而你救了我的命!非常感谢保罗分享你的才华和宝贵的时间来帮助我。多亏了你,我才恢复了内心的平静!
  • @dolphin20 乐于助人!如果你好奇,可以看看this other answer我发布了一个类似的问题,在那里我更深入地介绍了如何使用浏览器的开发工具来记录你的网络流量、发现和模仿 XHR 请求等。
猜你喜欢
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 2018-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多