【问题标题】:Finding only topmost posts in Disqus using R/Selenium使用 R/Selenium 仅在 Disqus 中查找最顶层的帖子
【发布时间】:2020-04-08 02:04:32
【问题描述】:

首先我为这篇文章的篇幅道歉,因为我想提供足够的细节来说明我正在尝试做的事情。

我正在尝试完善我用 R 编写的抓取应用程序以获取 Disqus cmets。到目前为止,我能够使用各种 RSelenium 功能获取特定页面上的所有 cmets。我现在要做的是从发布的 cmets 中获取一种树结构,即首先获取最顶层的 cmets,然后检查这些 cmets 是否有任何孩子。我作为示例使用的网站中的一个特定页面总共有 34 个 cmets,但其中只有 18 个是最上面的。其余的都是孩子或孩子的孩子。

我正在做的是在 Chrome 中打开一个页面并创建一个 webdriver,我使用 selectorgadget 来找到正确的选择器,如下所示:

1. elem <- remDr$findElement(using = "id", value = "posts")
2. elem.posts <- elem$findChildElements(using = "id", value = "post-list")
3. elem.posts <- elem$findElements(using = 'css selector', value = '.post~ .post+ .post')

在上面的代码中,第 1 行找到了帖子部分,然后如果我使用第 2 行,我会得到页面上的所有帖子,然后我使用下面的行来查找所有消息,所以如果上面有 34 个 cmets页面我都知道了。

elem.msgs &lt;- elem.posts[[1]]$findChildElements(using = 'css selector', '.post-message')

现在我已经意识到 cmets 的“树”结构对于我的数据项目可能很重要,并且我正在尝试首先获取最顶层的 cmets,然后查看每个热门评论以找到任何可用的子项。示例网页是here。为了获得 cmets,我使用了上面的第 1 行和第 3 行,结果是一个 16 行的列表,如果我使用 elem.posts[[1]]$getElementAttribute("id"),我会获得帖子 ID,以后可以使用它来查找每个热门评论。

这个 16 的列表应该是 18,我不明白为什么前两个 cmets 没有被捕获在列表中。在列表中未捕获到一些最顶层 cmets 的其他页面中也发生了这种情况。

我的问题是:我可以尝试使用什么来获取页面上所有最顶层的 cmets 而不会丢失任何评论?有没有更好的方法来获得最顶层的 cmets 而无需通过我没有经验的迂回方式?

感谢任何帮助或指导。

【问题讨论】:

    标签: r selenium


    【解决方案1】:

    您可以使用递归函数来降低帖子。只需要 RSelenium 即可获取页面源:

    library(xml2)
    library(RSelenium)
    library(jsonlite)
    selServ <- startServer()
    appURL <- "http://disqus.com/embed/comments/?base=default&version=90aeb3a56d1f2d3db731af14996f11cf&f=malta-today&t_i=article_67726&t_u=http%3A%2F%2Fwww.maltatoday.com.mt%2Fnews%2Fnational%2F67726%2Fair_malta_pilots_demands_30_basic_salary_increase&t_d=Air%20Malta%20pilots%E2%80%99%20demands%3A%2030%25%20basic%20salary%20increase%2C%20increased%20duty%20payments%2C%20double%20%E2%80%98denied%20leave%E2%80%99%20payment&t_t=Air%20Malta%20pilots%E2%80%99%20demands%3A%2030%25%20basic%20salary%20increase%2C%20increased%20duty%20payments%2C%20double%20%E2%80%98denied%20leave%E2%80%99%20payment&s_o=default"
    remDr <- remoteDriver()
    remDr$open()
    remDr$navigate(appURL)
    pgSource <- remDr$getPageSource()[[1]]
    remDr$close()
    selServ$stop()
    doc <- read_html(pgSource)
    appNodes <- xml_find_all(doc, "//ul[@id='post-list']/li[@class='post']")
    # write recursive function to get 
    content_fun <- function(x){
      main <- xml_find_all(x, "./div[@data-role]/.//div[@class='post-body']")
      main <- list(
        poster = xml_text(xml_find_all(main, ".//span[@class = 'post-byline']")),
        posted = xml_text(xml_find_all(main, ".//span[@class = 'post-meta']")),
        date = xml_attr(xml_find_all(main, ".//a[@class = 'time-ago']"), "title"),
        message = xml_text(xml_find_all(main, ".//div[@data-role = 'message']"))
      )
      # check for children
      children <- xml_find_all(x, "./ul[@class='children']/li[@class='post']")
      if(length(children) > 0){
        main$children <- lapply(children, content_fun)
      }
      main
    }
    
    postData <- lapply(appNodes, content_fun)
    

    例如这里是第三个帖子

    > prettify(toJSON(postData[[3]]))
    {
        "poster": [
            "\nMary Attard\n\n"
        ],
        "posted": [
            "\n•\n\n\na month ago\n\n"
        ],
        "date": [
            "Thursday, July 21, 2016 6:12 AM"
        ],
        "message": [
            "\nI give up. Air Malta should be closed down.\n"
        ],
        "children": [
            {
                "poster": [
                    "\nJoseph Lawrence\n\n Mary Attard\n"
                ],
                "posted": [
                    "\n•\n\n\na month ago\n\n"
                ],
                "date": [
                    "Thursday, July 21, 2016 7:43 AM"
                ],
                "message": [
                    "\nAir Malta should have been privatized or sold out right a long time ago. It is costing the TAX PAYER millions, it has for a long, long time.\n"
                ]
            },
            {
                "poster": [
                    "\nJ.Borg\n\n Mary Attard\n"
                ],
                "posted": [
                    "\n•\n\n\na month ago\n\n"
                ],
                "date": [
                    "Thursday, July 21, 2016 5:23 PM"
                ],
                "message": [
                    "\nYes - at this stage we taxpayers will be better off without Air Malta. We closed Malta Dry Docks and we survived. We can close Air Malta and we'll survive even better. After all, we have many more airlines serving us.\n"
                ]
            }
        ]
    }
    

    您可以根据需要清理和抓取哪些内容。

    【讨论】:

    • 我在执行appNodes &lt;- xml_find_all(doc, "//ul[@id='post-list']/li[@class='post']") 行时遇到了一些问题。我的 RStudio 因 R 会话中止而崩溃 R 遇到致命错误。会话被终止。你知道为什么吗?
    • 尝试使用命令行 R 运行代码。将排除 RStudio 问题。
    • 也许有人会觉得这很有用。我确实从命令行 R 运行了代码,但 read_html 出现了问题。不过感谢您的输入 :-) 问题在于我的默认 R 版本设置为 32 位版本。将版本设置为 64 位后,问题就消失了。
    • 我又遇到了麻烦 :-( 我想将评论 ID 添加到上面生成的 postData 列表中。使用 appNodesId &lt;- xml_attrs(appNodes, "//ul[@id='post-list']/li[@class='post']") 我可以获得以下列表最顶层评论的 ID,但修改同一行并将其添加到 content_fun 函数导致所有最顶层 id 被添加到列表的每个元素。我使用的修改行是 postId = xml_attrs(xml_find_all(main, "//ul[@id='post-list']/li[@class='post']"))。使用 xml_find_first 仅返回第一个 id但没有给孩子们。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    相关资源
    最近更新 更多