【问题标题】:Webscraping with Beautifulsoup: How to use next button if no href or nav-link?使用 Beautifulsoup 进行网页抓取:如果没有 href 或 nav-link,如何使用下一步按钮?
【发布时间】:2021-09-29 07:46:35
【问题描述】:

我正在尝试抓取url 并希望在所有可能的页面上获取所有公寓。在这个例子中,只有两个页面,我想:

  1. “单击下一个按钮”/转到第 2 页
  2. 如果没有下一步按钮,则转到最后一页

在我看过的教程中,例如this one,有一个指向他正在抓取的页面上的下一个按钮的 href 链接。在我的例子中,页面列表的 HTML 代码不包含任何 href 链接,但看起来像这样:

在其他教程中,他们可以通过查找网页中的链接来找到指向下一步按钮的 href 链接。当我这样做时,我只获得了网站的主要链接(尽管加载了一个嵌套的 url)并且没有找到任何下一步按钮。

nav = soup.nav

for url in nav.find_all('a'):
    print(url.get('href'))

您对在这种情况下如何访问下一个按钮的 url 有任何想法吗?

【问题讨论】:

    标签: python web web-scraping navigation


    【解决方案1】:

    您可以使用 CSS 和/或 XPath 选择器选择 html 树的任何元素部分。

    请链接stack overflow post that goes into detail how to do it in beautiful soup

    TLDR:use from lxml import etree 解析和支持 XPath

    Xpath 可能类似于 //div/button[@class='_132gv'] 或任何其他具体的东西查找XPath syntax

    您始终可以计算元素的数量、检查是否存在等,尤其是支持更多功能的 XPath。

    【讨论】:

    • 感谢您的指导,这对我来说还不够高级,但我会用 lxml、find_next 和 xpath 选择器深入研究这篇文章,看看这是否能解决问题。
    • 没问题,您可以随时检查我链接的 xpath 语法并在任何使用 chrome 的网站上练习,例如使用 chrome 中的 2 种方式之一(可能还有其他浏览器):F12 -> Console -> $x("<Your XPATH>") 示例给你页面上的所有div如下$x("//div")F12 -> Elements -> Click on the HTML and press CTL + F 现在在突出显示的同时直接使用您的 xpath/css 搜索
    【解决方案2】:

    我不是特别熟悉 Beautiful soup 的所有选项,但很可能假设您要点击的链接中有一个 href,所以这不起作用。该页面似乎是一个 SPA,也许这个下一个按钮是用一些请求数据并更新页面的 java 脚本(例如事件侦听器)实现的。

    似乎大部分数据是通过对https://www.booli.se/graphql 的API 调用加载的。右键单击该页面,单击检查,然后查看网络选项卡并单击下一步按钮。在请求正文中发送带有如下参数的请求:

    {
      "operationName": "searchForSale",
      "variables": {
        "input": {
          "page": 2,
          "filters": [
            {
              "key": "objectType",
              "value": "Lägenhet,Parhus,Radhus,Kedjehus"
            },
            {
              "key": "rooms",
              "value": "3,2,4"
            },
            {
              "key": "minLivingArea",
              "value": "60"
            }
        },
     "query": "query searchForSale($input: SearchRequest) {\n  search: searchForSale(input: $input) {\n    pages\n    totalCount\n    result {\n      __typename\n      ... on Listing {\n        booliId\n        blockedImages\n        descriptiveAreaName\n        livingArea {\n          formatted\n          __typename\n        }\n        listPrice {\n          formatted\n          raw\n          __typename\n        }\n        listSqmPrice {\n          formatted\n          __typename\n        }\n        latitude\n        longitude\n        daysActive\n        primaryImage {\n          id\n          __typename\n        }\n        objectType\n        rent {\n          formatted\n          raw\n          __typename\n        }\n        operatingCost {\n          raw\n          __typename\n        }\n        estimate {\n          price {\n            raw\n            formatted\n            __typename\n          }\n          __typename\n        }\n        rooms {\n          formatted\n          __typename\n        }\n        streetAddress\n        url\n        isNewConstruction\n        biddingOpen\n        upcomingSale\n        mortgageDeed\n        tenureForm\n        plotArea {\n          formatted\n          __typename\n        }\n        patio\n        hasFireplace\n        __typename\n      }\n      ... on Project {\n        booliId\n        name\n        url\n        booliUrl\n        numberOfListingsForSale\n        location {\n          namedAreas\n          __typename\n        }\n        developer {\n          name\n          id\n          __typename\n        }\n        image {\n          id\n          __typename\n        }\n        latestPriceChange\n        latitude\n        longitude\n        created\n        roomsList\n        livingAreaRange\n        listPriceRange\n        lowestProjectListPrice\n        __typename\n      }\n    }\n    __typename\n  }\n}\n"
    }
    

    您可以直接发送此请求并使用响应数据,而不是尝试转到下一页,从而根据您的需要调整请求中的变量。因此,如果需要,您可以在此处增加页面(或者甚至可以在无需点击页面的情况下获取所有数据)。

    编辑: 我的 API 不需要任何形式的身份验证,我向https://www.booli.se/graphql 发送一个带有正文的 POST 请求,这是邮递员中的一个示例:

    【讨论】:

    • 您好,感谢您的评论。我不完全明白你想让我尝试什么,我检查了 API 并为新开发人员关闭了它,所以我无法访问它(很遗憾)。
    • 没有指向另一个页面的 url(因此也没有 href),而是使用请求加载数据。我添加了一个示例,说明如何使用邮递员直接从 api 检索数据。我也更新了我的旧解释,希望这会有所帮助
    猜你喜欢
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 2020-10-04
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多