【问题标题】:Scrape using Perl regex in R在 R 中使用 Perl 正则表达式进行抓取
【发布时间】:2018-08-01 17:06:06
【问题描述】:

当你在 R 中抓取链接时使用 rvest 或 RSelenium,你可以通过定义 HTML 代码的开始部分来做到这一点,例如给定节点内的 href。如果我遇到以下链接怎么办:

<a href="www.website.com" data-tracking="click_body" data-tracking- 
data='{"touch_point_button":"photo"}' data-featured-name="listing_no_promo" >

如果我不想获取任何促销链接,那么我将使用(来自 XML 和 httr 包)以下代码:

library(XML)
library(httr)
response <- GET(yourLink)
parsedoc <- htmlParse(response)
xpathSApply(parsedoc, "//a[@data-featured-tracking='listing_no_promo']", 
xmlGetAttr, "href")

如果我想获取以 xpath 的“照片”部分结尾的链接,我应该怎么做:

data-tracking- data='{"touch_point_button":"photo"}'

不关心促销或没有促销部分?我的猜测是大括号在这里产生了一些噪音。

【问题讨论】:

  • data-tracking-data属性的值是一个JSON数据结构。如果你不能保证你想要匹配的总是像这样,那么用正则表达式解析会很棘手。

标签: r xml screen-scraping pcre httr


【解决方案1】:

我假设您的示例链接结构实际上如下(其中 data-tracking-data 是实际属性:

<a href="www.website.com" data-tracking="click_body" data-tracking-data=\'{"touch_point_button":"photo"}\' data-featured-name="listing_no_promo">link</a>

由于我不知道您正在使用哪个网站,因此我通过将您的链接添加到此页面的正文重新创建了一个 html 文档:

# I'm going to use the jsonlite and xml2 packages

library(jsonlite)
library(xml2)

# This page
stack_url <- "https://stackoverflow.com/questions/40934644/xpath-for-element-whose-attribute-value-ends-with-a-specific-string"

# Your html element example
test_a <- '<a href="www.website.com" data-tracking="click_body" data-tracking-data=\'{"touch_point_button":"photo"}\' data-featured-name="listing_no_promo" >link</a>'

# read in stackoverflow page
raw_page <- read_html(stack_url)
# read in the element a
raw_a <- read_html(test_a)

# add the link element from example to raw_page
xml_add_child(raw_page, raw_a)
# This is just to show that the tag you provided is mixed in with multiple link elements... since this would be the case in your actual use i assume
xml_find_all(raw_page,".//a") %>% tail()

{xml_nodeset (6)}
[1] <a href="https://www.facebook.com/officialstackoverflow/" class="-link">Facebook</a>
[2] <a href="https://twitter.com/stackoverflow" class="-link">Twitter</a>
[3] <a href="https://linkedin.com/company/stack-overflow" class="-link">LinkedIn</a>
[4] <a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license">cc by-sa 3.0</a>
[5] <a href="https://stackoverflow.blog/2009/06/25/attribution-required/" rel="license">attribution required</a>
[6] <a href="www.website.com" data-tracking="click_body" data-tracking-data='{"touch_point_button":"photo"}' data-f ...

所以我们的xml_document 现在存储到raw_page,然后我们将使用 xpath 来查找我们想要的内容

.//a[attribute::*[contains(.,'{') or contains(.,'photo')] and @data-tracking]

# Our xpath pattern reads as:
# 
# - .//a[ -> find all 'a' html elements where
# - attribute::*[contains(.,'{') or contains(.,'photo')] -> any(*) attribute containing either a '{' OR the string 'photo'
# - and @data-tracking -> and the element must have the attribute data-tracking, but it doesn't matter what the value is
# - ] -> end

在短期内:
查找所有具有 data-tracking 属性并且具有包含单词 photo 或字符 { 的属性的链接em>

our_xpath <- ".//a[attribute::*[contains(.,'{') or contains(.,'photo')] and @data-tracking]"
# Extract all of the matching elements using our xpath
# Get all the attribute values for data-tracking-data
# Parse from JSON
xml_find_all(raw_page,our_xpath) %>% xml_attr("data-tracking-data") %>% fromJSON()

结果:

$touch_point_button
[1] "photo"

我无法针对您的页面进行测试...但是如果您发布网址,我很乐意确保它相应地工作。

【讨论】:

【解决方案2】:
//*[ends-with(@data-tracking-data, '"photo"}')]/@href

从您的示例中,如果 data-tacking-data 以字符串 "photo"}

结尾,此 xpath 将为您提供 href 属性

【讨论】:

    猜你喜欢
    • 2015-02-16
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多