Как извлечь ключевые слова из URL-адреса страницы результатов поиска Google?
Одна из переменных в моем наборе данных содержит URL-адреса страниц результатов поиска Google. Я хочу извлечь ключевые слова для поиска из этих URL.
Пример набора данных:
keyw <- structure(list(user = structure(c(1L, 1L, 1L, 2L, 2L, 2L), .Label = c("p1", "p2"), class = "factor"),
url = structure(c(3L, 5L, 4L, 1L, 2L, 6L), .Label = c("https://www.google.nl/search?q=five+fingers&ie=utf-8&oe=utf-8&gws_rd=cr,ssl&ei=kERoVbmMO6fp7AaGioCYAw", "https://www.google.nl/search?q=five+fingers&ie=utf-8&oe=utf-8&gws_rd=cr,ssl&ei=kERoVbmMO6fp7AaGioCYAw#safe=off&q=five+short+fingers+", "https://www.google.nl/search?q=high+five&ie=utf-8&oe=utf-8&gws_rd=cr,ssl&ei=bENoVZSqL4ON7Qb5wIDIDg", "https://www.google.nl/search?q=high+five&ie=utf-8&oe=utf-8&gws_rd=cr,ssl&ei=bENoVZSqL4ON7Qb5wIDIDg#safe=off&q=high+five+with+a+chair", "https://www.google.nl/search?q=high+five&ie=utf-8&oe=utf-8&gws_rd=cr,ssl&ei=bENoVZSqL4ON7Qb5wIDIDg#safe=off&q=high+five+with+handshake", "https://www.youtube.com/watch?v=6HOallAdtDI"), class = "factor")),
.Names = c("user", "url"), class = "data.frame", row.names = c(NA, -6L))
До сих пор мне удалось извлечь части ключевых слов поиска из URL-адресов с помощью:
keyw$words <- sapply(str_extract_all(keyw$url, 'q=([^&#]*)'),paste, collapse=",")
Однако это все еще не дает мне желаемого результата. Вышеприведенный код дает следующий результат:
> keyw$words
[1] "q=high+five"
[2] "q=high+five,q=high+five+with+handshake"
[3] "q=high+five,q=high+five+with+a+chair"
[4] "q=five+fingers"
[5] "q=five+fingers,q=five+short+fingers+"
[6] ""
Есть три проблемы с этим выходом:
- Мне нужны только слова в виде строки. Вместо
q=high+five
мне нужно high,five
.
- Как показывают строки 2, 3 и 5, URL иногда содержит две части с ключевыми словами поиска. Поскольку первая часть - это просто ссылка на предыдущий поиск, мне нужен только второй поисковый запрос.
- Если URL-адрес не является URL-адресом поисковой страницы Google, он должен вернуть
NA
Желаемый результат должен быть:
> keyw$words
[1] "high,five"
[2] "high,five,with,handshake"
[3] "high,five,with,a,chair"
[4] "five,fingers"
[5] "five,short,fingers"
[6] NA
Как это решить?
Ответы
Ответ 1
Еще одно обновление после комментария (выглядит слишком сложно, но это лучшее, что я могу достичь на этом этапе:)):
keyw$words <- sapply(str_extract_all(str_extract(keyw$url,"https?:[/]{2}[^/]*google.*[/].*"),'(?<=q=|[+])([^$+#&]+)(?!.*q=)'),function(x) if(!length(x)) NA else paste(x,collapse=","))
> keyw$words
[1] "high,five" "high,five,with,handshake" "high,five,with,a,chair" "five,fingers"
[5] "five,short,fingers" NA
Это изменение является фильтром при вводе в str_extract_all, измененным из полного вектора на "фильтрованный", чтобы соответствовать регулярному выражению, любое регулярное выражение может идти туда, чтобы соответствовать более или менее точно, что вы хотите.
Здесь регулярное выражение:
-
http
litteraly http
-
s?
0 или 1 с
-
[/]{2}
ровно две слэши (используя класс символов, избегая необходимости уродливой конструкции \\/
и читайте вещи более читабельными
-
[^/]*
любое количество символов без косой черты
-
google.*[/]
соответствует litteraly google, за которым следует что-либо до последнего /
-
.*
наконец-то совпадет с чем-то или нет после последней косой черты
Замените * на +, где бы вы ни хотели, чтобы параметр (+
требовал, чтобы предыдущий символ присутствовал хотя бы один раз)
Обновление, сильно вдохновленное @BrodieG, вернет NA, если нет совпадения, но будет по-прежнему соответствовать любому сайту, если там q=
в параметрах.
По-прежнему с тем же методом:
> keyw$words <- sapply(str_extract_all(keyw$url,'(?:(?<=q=|\\+)([^$+#&]+)(?!.*q=))'),function(x) if(!length(x)) NA else paste(x,collapse=","))
> keyw$words
[1] "high,five" "high,five,with,handshake" "high,five,with,a,chair"
[4] "five,fingers" "five,short,fingers" NA
Демо-версия Regex
(Lookbehind (?<=)
убедитесь, что q = или + где-то перед словом и отрицательный lookahead (?!)
убедитесь, что мы не можем найти q = до конца строки.
Класс символов запрещает знак + останавливаться на каждом слове.
Ответ 2
Или, может быть, это
gsub("\\+", ",", gsub(".*q=([^&#]*[^+&]).*", "\\1", keyw$url))
# [1] "high,five" "high,five,with,handshake" "high,five,with,a,chair"
# [4] "five,fingers" "five,short,fingers"
Ответ 3
Обновление (заимствование части регулярного выражения от Дэвида):
dat <- as.character(keyw$url)
pat <- "^https://www\\.google\\.nl/.*\\bq=([^&]*[^&+]).*"
sapply(
regmatches(dat, regexec(pat, dat)),
function(x) if(!length(x)) NA else gsub("\\+", ",", x[[2]])
)
Выдает:
[1] "high,five" "high,five,with,handshake" "high,five,with,a,chair"
[4] "five,fingers" "five,short,fingers" NA
Использование:
pat <- "^https://www\\.google.(?:com?.)?[a-z]{2,3}/.*\\b?q=([^&]*[^&+]).*"
учитывает все специфические для Google домены (источник)
Или:
gsub("\\+", ",", sub("^.*\\bq=([^&]*).*", "\\1", keyw$url))
Выдает:
[1] "high,five" "high,five,with,handshake" "high,five,with,a,chair"
[4] "five,fingers" "five,short,fingers,"
Здесь мы используем жадность, чтобы убедиться, что мы пропустим все до последней части q=...
, а затем используем стандартный трюк sub
/\\1
для захвата того, что мы хотим. Наконец, замените +
на ,
.
Ответ 4
Там должен быть более чистый способ, но может быть что-то вроде:
sapply(strsplit(keyw$words, "q="), function(x) {
x <- if (length(x) == 2) x[2] else x[3]
gsub("+", ",", gsub("\\+$", "", x), fixed = TRUE)
})
# [1] "high,five" "high,five,with,handshake" "high,five,with,a,chair"
# [4] "five,fingers" "five,short,fingers"
Все в одном:
keyw$words <- sapply(str_extract_all(keyw$url, 'q=([^&#]*)'),function(x) {
x <- if (length(x) == 2) x[2] else x[1]
x <- gsub("+", ",", gsub("\\+$", "", x), fixed = TRUE)
gsub("q=","",x, fixed = TRUE)
})
Ответ 5
Я бы попробовал:
x<-as.character(keyw$url)
vapply(regmatches(x,gregexpr("(?<=q=)[^&]+",x,perl=TRUE)),
function(y) paste(unique(unlist(strsplit(y,"\\+"))),collapse=","),"")
#[1] "high,five" "high,five,with,handshake"
#[3] "high,five,with,a,chair" "five,fingers"
#[5] "five,fingers,short"