在下面的链接中有一个按国家(地区)分类的税表,我想将其刮入带有“国家(地区)”和“税收(Tax)”列的数据框中。
我尝试如下使用rvest软件包来获取“国家/地区”列,但生成的列表为空,我不明白为什么。
对于解决这个问题,我将不胜感激。
library(rvest)
d1 <- read_html(
"http://taxsummaries.pwc.com/ID/Corporate-income-tax-(CIT)-rates"
)
TaxCountry <- d1 %>%
html_nodes('.countryNameQC') %>%
html_text()
答案 0 :(得分:1)
在浏览器中运行javascript时,将动态加载数据并更改DOM。 rvest
不会发生这种情况。
在浏览器中,以下选择器将隔离您的节点:
.twoCountryWrapper .countryNameAndYearQC:nth-child(1) .countryNameQC
.twoCountryWrapper .countryNameAndYearQC:nth-child(1) .countryYear
.twoCountryWrapper .countryNameAndYearQC:nth-child(2) .countryNameQC
.twoCountryWrapper .countryNameAndYearQC:nth-child(2) .countryYear
但是,这些类甚至都没有出现在rvest
返回中。
感兴趣的数据实际上存储在几个节点中;所有ID的公共前缀都为dspQCLinks
。内部数据如下所示:
因此,您可以使用css attribute = value以运算符(^)开头的语法来收集所有这些节点:
html_nodes(page, "[id^=dspQCLinks]")
然后提取文本并合并为一个字符串
paste(html_text(html_nodes(page, "[id^=dspQCLinks]")), collapse = '')
现在表中的每一行都由!,
分隔,因此我们可以对其进行拆分以生成行:
info = strsplit(paste(html_text(html_nodes(page, "[id^=dspQCLinks]")), collapse = ''),"!,")[[1]]
示例行将如下所示:
"Albania@/uk/taxsummaries/wwts.nsf/ID/Albania-Corporate-Taxes-on-corporate-income@15"
如果我们在@
上拆分每一行,则所需数据位于索引1和3:
arr = strsplit(i, '@')[[1]]
country <- arr[1]
tax <- arr[3]
由于@Brian的反馈,我删除了构建数据框所必需的循环,并用引号@Brian代替,
str_split_fixed(info, "@", 3)
[哪个]为您提供了一个字符矩阵,可以将其直接强制转换为数据框。
df <- data.frame(str_split_fixed(info, "@", 3))
然后删除df底部的空行。
df <- df[df$Country != "",]
df示例:
R
library(rvest)
library(stringr)
library(magrittr)
page <- read_html('http://taxsummaries.pwc.com/ID/Corporate-income-tax-(CIT)-rates')
info = strsplit(paste(html_text(html_nodes(page, "[id^=dspQCLinks]")), collapse = ''),"!,")[[1]]
df <- data.frame(str_split_fixed(info, "@", 3))
colnames(df) <- c("Country","Link","Tax")
df <- subset(df, select = c("Country","Tax"))
df <- df[df$Country != "",]
View(df)
Python:
我首先在python中这样做,对我来说更快:
import requests
from bs4 import BeautifulSoup as bs
import pandas as pd
r = requests.get('http://taxsummaries.pwc.com/ID/Corporate-income-tax-(CIT)-rates')
soup = bs(r.content, 'lxml')
text = ''
for i in soup.select('[id^=dspQCLinks]'):
text+= i.text
rows = text.split('!,')
countries = []
tax_info = []
for row in rows:
if row:
items = row.split('@')
countries.append(items[0])
tax_info.append(items[2])
df = pd.DataFrame(list(zip(countries,tax_info)))
print(df)
阅读: