手机信息采集 ——基于ebay网站Apple手机

在本案例分析中,我们要采集的是ebay网站上销售们的众多手机的价格、消费者评分和产品识别码等数据。ebay销售的产品很广,让我们能对每家大型手机生产商的产品进行全面的总结。
本案例分析利用了Rcurl、XML和stringr组件,它利用了Rcurl curl句柄。并具备搜索页操控、链接提取和页面下载等特性。运用以上组件,可以在源代码中搜索信息并把Xpath运用到实际问题中。此外,在本案例分析中,创建了一个SQLite数据库,它能以一致的方式保存数据,并可以用于下一个案例分析。
本文旨在构建一个SQLite数据库,用它存放我们迄今提取的数据,并留出加入更多信息的空间。以ebay网站上250个Apple手机信息为例,进行信息的提取、页面的解析和数据的存储。

内容如下所示:
1. 页面搜索
1.1查找指定品牌手机
1.2提取搜索结果页面信息
2. 采集、解析所有产品页面
2.1采集所有产品页面
2.2提取所有产品信息
2.3创建数据框保存
3. 存储数据
3.1用于存储的表的定义
3.2考虑未来的存储的数据表的定义
3.3检查表的函数
3.4保存数据的函数**

1.页面搜索
1.1查找指定品牌的手机
先加载必要组件。Stringr组件可以提取和处理文本片段,XML和RCurl负责主要的抓取工作。
运行程序:
install.packages(“stringr”)
install.packages(“XML”)
install.packages(“RCurl”)
library(stringr)
library(XML)
library(RCurl)
将生产商的搜索网页用getURL函数进行解析,并且建立一个空的SearchPages用于保存解析完的网页。

运行程序:
url<-“https://www.ebay.com/sch/i.html?_from=R40
&_trksid=m570.l1313&_nkw=Apple”
firstSearchPage <- getURL(url)
SearchPages <- list()
SearchPages[[1]] <- firstSearchPage

关于生产商的搜索网页有多页,我们需要下载后面的搜索页面,并把它保存在一个列表对象里。我们创建一个for循环用来获取前五个搜索结果页面。每次都会提取一个下一页的链接,并把网页下载和保存到列表对象中。其中,最重要的是我们需要构建一个xpath表达式,在网页的“审查元素”中我们可以发现下一页是由“class”和“rel”共同决定的,在所有span中找到符合“class”和“rel”,并提取“href”(即网址)。

运行程序:
xpath <- “//a[@class=’x-pagination__control’ and @rel=’next’]/@href”
nextPageLink <- xpathApply( htmlParse(SearchPages[[1]]), xpath)
nextPageLink

运行结果:
href
“https://www.ebay.com/sch/i.html?_from=R40&_nkw=Apple&_pgn=2”
attr(,”class”)

提取下一页的链接:
运行程序:
for( i in 2:5 ){
nextPageLink <- xpathApply( htmlParse(SearchPages[[i-1]]), xpath)
SearchPages[[ i ]] <- getURL(nextPageLink)
}

nextPageLink <- xpathApply( htmlParse(SearchPages[[2]]), xpath)
nextPageLink

运行结果:
[[1]]
href
“https://www.ebay.com/sch/i.html?_from=R40&_nkw=Apple&_pgn=3”
attr(,”class”)
[1] “XMLAttributeValue”
attr(,”class”)
[1] “XMLNodeSet”

nextPageLink <- xpathApply( htmlParse(SearchPages[[3]]), xpath)
nextPageLink
[[1]]
href
“https://www.ebay.com/sch/i.html?_from=R40&_nkw=Apple&_pgn=4”
attr(,”class”)
[1] “XMLAttributeValue”
attr(,”class”)
[1] “XMLNodeSet”
nextPageLink <- xpathApply( htmlParse(SearchPages[[4]]), xpath)
nextPageLink
[[1]]
href
“https://www.ebay.com/sch/i.html?_from=R40&_nkw=Apple&_pgn=5”
attr(,”class”)同样在提取产品信息时,也需要从“审查元素”中找到合适的“xpath”表达式来采集必要的数据。
1.2提取产品信息
我们要提取的第一个信息就是搜索结果页面的产品标题。利用“审查元素”工具,我们可以发现标题是 < h3 >节点的一部分,运用审查元素里的信息来构建一个关于产品标题的xpath表达式://h3[@class=’s-item__title’]。由于已经获取了要从中提取数据的搜索结果页面,所以我们将其整合成一个函数,并且用lapply函数来从所有页面提取信息。
(1) 提取标题
运行程序:
xpathApply( htmlParse(SearchPages[[1]]), “//h3[@class=’s-item__title’]”, xmlValue)[1:2]

运行结果:
“Apple iPhone 7 - 32GB 128GB 256GB - UNLOCKED - All Colours - 1 Year Warranty”
“Apple iPhone 8 64gb Space Gray 24 months guarantee Italy”

运行程序:
extractTitle <- function(x){
unlist(xpathApply( htmlParse(x), “//h3[@class=’s-item__title’]”, xmlValue))
}
titles <- unlist(lapply(SearchPages, extractTitle))
titles[1:5]

运行结果:
[1] “Apple iPhone 7 - 32GB 128GB 256GB - UNLOCKED - All Colours - 1 Year Warranty”
[2] “Apple iPhone 8 64gb Space Gray 24 months guarantee Italy”
[3] “Apple iPhone 6S - 16GB 32GB 64GB 128GB -Gold/Silver/Grey/Rose- UNLOCKED/SIMFREE”
[4] “Apple iPhone 7 128gb Jet Black + Accessories + Shipping + Warranty 12 months”
[5] “Apple iPhone 8 64gb Red guarantee Italy 24 months”
我们要提取的信息第二个就是搜索结果页面的产品链接。利用“审查元素”工具,我们可以发现标题是节点的一部分,运用审查元素里的信息来构建一个关于产品标题的xpath表达式://a[@class=’s-item__link’]/@href。由于已经获取了要从中提取数据的搜索结果页面,所以我们将其整合成一个函数,并且用lapply函数来从所有页面提取信息。
(2) 提取链接
运行程序:
xpathApply( htmlParse(SearchPages[[1]]), “//a[@class=’s-item__link’]/@href”)[1:2]

运行结果:
[[1]] href
“https://www.ebay.com/itm/Apple-iPhone-7-32GB-128GB-256GB-UNLOCKED-All-Colours-1-Year-Warranty/382440661440?epid=225303708&hash=item590b3d61c0:m:mKQepuKr_vqOKemMvtyq7AA”
[[2]] href
“https://www.ebay.com/itm/APPLE-IPHONE-8-64GB-SPACE-GRAY-GARANZIA-ITALIA-24-MESI/142633355428?epid=5013131415&hash=item21359c48a4:g:nrYAAOSwor1aeD2h”
attr(,”class”)
[1] “XMLAttributeValue”

运行程序:
extractLink <- function(x){
unlist(xpathApply( htmlParse(x), “//a[@class=’s-item__link’]/@href”))
}
names <- unlist(lapply(SearchPages, extractLink))
在提取完链接后由于存在空格和href,我们用str_extract_all来只将链接提取下来,具体效果如下:
运行程序:
links <- unlist(str_extract_all(names,”http.+”))
links[1:5]

运行结果:
[1] “https://www.ebay.com/itm/Apple-iPhone-7-32GB-128GB-256GB-UNLOCKED-All-Colours-1-Year-Warranty/382440661440?epid=225303708&hash=item590b3d61c0:m:mKQepuKr_vqOKemMvtyq7AA”
[2] “https://www.ebay.com/itm/APPLE-IPHONE-8-64GB-SPACE-GRAY-GARANZIA-ITALIA-24-MESI/142633355428?epid=5013131415&hash=item21359c48a4:g:nrYAAOSwor1aeD2h”
[3] “https://www.ebay.com/itm/Apple-iPhone-6S-16GB-32GB-64GB-128GB-Gold-Silver-Grey-Rose-UNLOCKED-SIMFREE/202085839828?epid=216278648&hash=item2f0d4133d4:m:mFe_I9iEm-Qws_yA41FxAAA”
[4] “https://www.ebay.com/itm/APPLE-IPHONE-7-128GB-JET-BLACK-ACCESSORI-SPEDIZIONE-GARANZIA-12-MESI/262914625411?hash=item3d36eecf83:g:DqEAAOSwF25bGrHB”
[5] “https://www.ebay.com/itm/APPLE-IPHONE-8-64GB-RED-GARANZIA-ITALIA-24-MESI/153054066501?hash=item23a2bbb745:g:UrUAAOSwgStbIPX5”
我们利用getFirstPage函数来将关于Apple的250个产品网页下载下来,并且用fname1这个函数表达式来个各个网页进行命名。
运行程序:
keyword <- c(“Apple”)
Pages<-list()
getFirstPage <-function(keyword,forceDownload=F){
for (i in 1:length(links)) {
Pages[i] <- getURL(links[i])
fname1<-paste0(keyword,” ProducPage “,i,”.html”)
writeLines(Pages[[i]],fname1)
}}
getFirstPage(keyword)
我们在下载时都需要建立链接,为了节省时间我们创建一个句柄,每次对getURL的调用会重复使用它。我们还在函数中建立语句使服务器每隔10次下载就停顿一次,并把链接向量拆成10个分块,并对分块进行循环,在函数中解析所有网页。
2.采集、解析所有产品页面
2.1采集所有产品页面
运行程序:
chunk <- function(x,n) split(x, ceiling(seq_along(x)/n))
Links <- chunk(links,10)
curl <- getCurlHandle()
ProductPages <- list()
counter <- 1
for(i in 1:length(Links)){
ProductPages <- c(ProductPages, getURL(Links[[i]],curl = curl))
Sys.sleep(0.5)
}
ParsedProductPages <- lapply(ProductPages, htmlParse)
length(ProductPages)

2.2提取所有产品信息
在采集了所有产品页面之后,我们在产品网页中进行提取产品价格的操作。利用“审查元素”工具,我们可以发现标题是节点的一部分,运用审查元素里的信息来构建一个关于产品标题的xpath表达式://span[@class=”notranslate”]。并将其整合成一个函数,并且用lapply函数来从所有页面提取信息。对xpathapply的调用会给一些无价格信息的商品NULL,对于这种情况,我们要检查结果的长度。如果结果的长度为0,我们就把它替换成NA。
(1) 产品价格
运行程序:
extractPrice <- function(x){
x <- xpathApply( x, ‘//span[@class=”notranslate”]’, xmlValue )
if( length(x)==0 ) x <- NA
x <- unlist(x)
return(x)
}
prices <- unlist(lapply(ParsedProductPages, extractPrice))
names(prices) <- NULL
prices <- prices[1:250]
prices[1:5]

运行结果:
“GBP 244.95” “EUR 634.99” “GBP 124.95” “EUR 389.90” “EUR 649.99”
在采集了所有产品页面之后,我们在产品网页中进行提取打分人数的操作。利用“审查元素”工具,我们可以发现打分人数是节点的一部分,运用审查元素里的信息来构建一个关于产品标题的xpath表达式://span[@class = ‘mbg-l’]/a。并将其整合成一个函数,并且用lapply函数来从所有页面提取信息。对于结果的长度为0的情况,我们就把它替换成NA。
(2) 星星数
运行程序:
xpathApply( ParsedProductPages[[1]], “//span[@class = ‘mbg-l’]/a”,xmlValue)

运行结果:
“65432”

设置成一个函数:

运行程序:
extractStar <- function(x){
x <- xpathApply( x, “//span[@class = ‘mbg-l’]/a”,xmlValue)
if( length(x)==0 ){
x <- NA
}else{
x <- x[[1]]
}
return( as.numeric(x) )
}
stars <- unlist(lapply(ParsedProductPages, extractStar))
names(stars) <- NULL
stars[1:5]

运行结果:
65432 16209 65432 38195 16209
在采集了所有产品页面之后,每一个产品都有ebay给定的独一无二的产品识别码,我们在产品网页中进行提取产品识别码的操作。利用“审查元素”工具,我们可以发现产品识别码是节点的一部分,运用审查元素里的信息来构建一个关于产品标题的xpath表达式://div[@class=’u-flL iti-act-num’]。并将其整合成一个函数,并且用lapply函数来从所有页面提取信息。对于结果的长度为0的情况,我们就把它替换成NA。
(3) 提取eBay item number(产品识别码)

运行程序:
xpathApply( ParsedProductPages[[1]], “//div[@class=’u-flL iti-act-num’]”,xmlValue)

运行结果:
[[1]]
[1] “382440661440”

设置成一个函数:

运行程序:
extractASIN <- function(x){
x <- xpathApply( x, “//div[@class=’u-flL iti-act-num’]”, xmlValue)
x <- str_trim(unlist(x))
if( length(x)==0 ) x <- NA
return( x )
}
asins <- unlist(lapply(ParsedProductPages, extractASIN))
names(asins) <- NULL
asins[1:5]

运行结果:
“382440661440” “142633355428” “202085839828” “262914625411” “153054066501”
我们在产品网页中进行提取产品型号的操作。利用“审查元素”工具,我们可以发现产品型号是< h2>节点的一部分,运用审查元素里的信息来构建一个关于产品标题的xpath表达式://h2[@itemprop=’model’]。并将其整合成一个函数,并且用lapply函数来从所有页面提取信息。对于结果的长度为0的情况,我们就把它替换成NA。
(4) 产品型号
运行程序:
xpathApply( ParsedProductPages[[1]], “//h2[@itemprop=’model’]”,xmlValue)

运行结果:
[1] “iPhone 7”

设置成一个函数:

运行程序:
extractModel <- function(x){
xpath <- “//h2[@itemprop=’model’]”
x <- xpathApply( x, xpath, xmlValue)
x <- str_trim(unlist(x))
if( length(x)==0 ) x <- NA
return( x )
}
models <- unlist(lapply(ParsedProductPages, extractModel))
names(models) <- NULL
models[1:5]

运行结果:
[1] “iPhone 7” NA “iPhone 6s”
[4] NA NA
2.3创建数据框
我们将从网页中提取的数据放入命名为“phones”的数据框中。

运行程序:
phones <- data.frame(brands=”Apple”, prices, stars, asins, models, titles, links , timestamp=as.character(Sys.time()), stringsAsFactors=F)

如果我们想要在数据框中加入一个新的列,可以用within这个函数来进行添加。
运行程序:
fname1 <- list()
for(i in 1:length(links))
{
fname1[i]<-paste0(“Apple”,” ProducPage “,i,”.html”)
}
fnames<-fname1
phones<-within(phones,{fnames<-fname1})
我们将数据进行保存,命名为phones.Rdata。
save(phones, file=”phones.Rdata”)

3.数据存储
下面我们要创建一个SQLite数据库,用它来存放我们提取的数据信息,并且留出加入更多信息的空间。我们首先需要下载和加载组件。

运行程序:
load(“phones.Rdata”)
install.packages(“RSQLite”)
library(RSQLite)

我们用dbConnect创建一个新的数据库,命名为“ebay.db”,并建立到该数据库的连接。

运行程序:
sqlite <- dbDriver(“SQLite”)
con <- dbConnect(sqlite, “ebay.db”)

3.1 用于存储的表的定义
我们要创建一个表来保存ASIN,并在之后把所有其他数据都通过外键关联到这个变量。我们用UNIQUE语句来保证该列中没有重复数据,并加入ON CONFLICT IGNORE语句,当有违反唯一性的操作发生时,不需要报错,直接对其进行忽略。if(!dbExistsTable())也是用来预防出错的,如果表已经存在,就不再发送SQL请求。
创建一个包含ASIN的表

运行程序:
createPhones <- function(con){
if(!dbExistsTable(con,”phones”)){
sql <- “CREATE TABLE phones (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
asin CHAR,
UNIQUE(asin) ON CONFLICT IGNORE);”
dbGetQuery(con, sql)
}else{
message(“table already exists”)
}
}
我们要创建一个表来保存生产商,并在之后把所有其他数据都通过外键关联到这个变量。我们用UNIQUE语句来保证该列中没有重复数据,并加入ON CONFLICT IGNORE语句,当有违反唯一性的操作发生时,不需要报错,直接对其进行忽略。if(!dbExistsTable())也是用来预防出错的,如果表已经存在,就不再发送SQL请求。

运行程序:
#生产商
createProducers <- function(con){
if(!dbExistsTable(con, “producers”)){
sql <- “CREATE TABLE producers (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
producer CHAR,
UNIQUE(producer) ON CONFLICT IGNORE);”
dbGetQuery(con, sql)
}else{
message(“table already exists”)
}
}
我们要创建一个表来保存手机型号,并在之后把所有其他数据都通过外键关联到这个变量。我们用UNIQUE语句来保证该列中没有重复数据,并加入ON CONFLICT IGNORE语句,当有违反唯一性的操作发生时,不需要报错,直接对其进行忽略。if(!dbExistsTable())也是用来预防出错的,如果表已经存在,就不再发送SQL请求。

运行程序:
#手机型号
createModels <- function(con){
if(!dbExistsTable(con, “models”)){
sql <- “CREATE TABLE models (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
model CHAR,
UNIQUE(model) ON CONFLICT IGNORE);”
dbGetQuery(con, sql)
}else{
message(“table already exists”)
}
}
我们要创建一个表来保存链接,并在之后把所有其他数据都通过外键关联到这个变量。我们用UNIQUE语句来保证该列中没有重复数据,并加入ON CONFLICT IGNORE语句,当有违反唯一性的操作发生时,不需要报错,直接对其进行忽略。if(!dbExistsTable())也是用来预防出错的,如果表已经存在,就不再发送SQL请求。

运行程序:
#链接
createLinks <- function(con){
if(!dbExistsTable(con, “links”)){
sql <- “CREATE TABLE links (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
link TEXT);”
dbGetQuery(con, sql)
}else{
message(“table already exists”)
}
}

3.2考虑未来存储的数据表定义
我们要创建一个表来保存评论,并在之后把所有其他数据都通过外键关联到这个变量。我们用UNIQUE语句来保证该列中没有重复数据,并加入ON CONFLICT IGNORE语句,当有违反唯一性的操作发生时,不需要报错,直接对其进行忽略。if(!dbExistsTable())也是用来预防出错的,如果表已经存在,就不再发送SQL请求。里面可以包含对应的ASIN,星星数,认为有用或者无用的人数及其总和,评论发表的日期,评论标题以及实际评论的文字。

运行程序:
#评论
createReviews <- function(con){
if(!dbExistsTable(con,”reviews”)){
sql <- “CREATE TABLE reviews (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
asin TEXT,
stars INTEGER,
helpfulyes INTEGER,
helpfulno INTEGER,
helpfulsum INTEGER,
date TEXT,
title TEXT,
text TEXT,
UNIQUE(asin, stars, date, title, text) ON CONFLICT IGNORE);”
dbGetQuery(con, sql)
}else{
message(“table already exists”)
}
}
创建一个“reviewsMeta”来保存对于某个型号的所有评论的元信息,其中包含了对应的ASIN和给出不同星星数的人数。

运行程序:
# 某个型号的所有评论信息
createReviewsMeta <- function(con){
if(!dbExistsTable(con,”reviewsMeta”)){
sql <- “CREATE TABLE reviewsMeta (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
asin TEXT,
one INTEGER,
two INTEGER,
three INTEGER,
four INTEGER,
five INTEGER,
UNIQUE(asin) ON CONFLICT REPLACE);”
dbGetQuery(con, sql)
}else{
message(“table already exists”)
}
}
我们上述所有创建表的函数包装到一个defineDatabase函数里并执行它:

运行程序:
defineDatabase <- function(con){
createPhones(con)
createProducers(con)
createModels(con)
createLinks(con)
createReviews(con)
createReviewsMeta(con)
}

3.3检查表的函数
我们还定义了一个dropAll函数,它会对我们在数据库中创建的数据表和视图进行检查,查看是否存在,并且利用drop table和drop view语句删除数据库中的所有数据表和视图。我们一般情况下不需要使用该语句。
逆转——会丢失所有数据

运行程序:
dropAll <- function(con){
sql <- “select ‘drop table ’ || name || ‘;’ from sqlite_master
where type = ‘table’;”
tmp <- grep(“sqlite_sequence”,unlist(dbGetQuery(con,sql)),
value=T,invert=T)
for(i in seq_along(tmp)) dbGetQuery(con,tmp[i])
sql <- “select ‘drop view ’ || name || ‘;’ from sqlite_master
where type = ‘view’;”
tmp <- grep(“sqlite_sequence”,unlist(dbGetQuery(con,sql)),
value=T,invert=T)
for(i in seq_along(tmp)) dbGetQuery(con,tmp[i])
}
dropAll(con)

3.4 保存数据的函数
之前我们所做的工作是抓取数据和构建数据库结构的函数,并没有将数据加入到数据库中。接下来我们就要将数据进行保存。
首先,我们进行ASIN的添加和保存。我们需要先查询有哪些ASIN已经存在在数据库中,对于数据库中不存在的ASIN,我们创建SQL语句将其加入到相应的数据库中。其中,unique函数表示“不加入重复行”,str_c函数表示“将字符串进行串联”。

运行程序:
#添加ASIN
addASINs <- function(x, con){
message(“adding phones …”)
asinsInDB <- unlist(dbReadTable(con,”phones”)[“asin”])
asinsToAdd <- unique(x asins[!(x a s i n s [ ! ( x asins[!(xasins %in% asinsInDB)])
for(i in seq_along(asinsToAdd)){
sql <- str_c(“INSERT INTO phones (asin) VALUES (‘”,
asinsToAdd[i], “’) ;”)
dbGetQuery(con, sql)
}
}
其次,我们进行生产商的添加和保存。我们需要先查询有哪些生产商已经存在在数据库中,对于数据库中不存在的生产商,我们创建SQL语句将其加入到相应的数据库中。其中,unique函数表示“不加入重复行”,str_c函数表示“将字符串进行串联”。

运行程序:
#添加生产商
addProducers <- function(x, con){
message(“adding producers …”)
producersInDB <- unlist(dbReadTable(con,”producers”)[“producer”])
producersToAdd <- unique(x brands[!(x b r a n d s [ ! ( x brands[!(xbrands %in% producersInDB)])
for(i in seq_along(producersToAdd)){
sql <- str_c(“INSERT INTO producers (producer) VALUES (‘”,
producersToAdd[i], “’) ;”)
dbGetQuery(con, sql)
}
}
再次,我们进行型号的添加和保存。我们需要先查询有哪些型号已经存在在数据库中,对于数据库中不存在的型号,我们创建SQL语句将其加入到相应的数据库中。其中,unique函数表示“不加入重复行”,str_c函数表示“将字符串进行串联”。

运行程序:
#添加型号
addModels <- function(x, con){
message(“adding models …”)
modelsInDB <- unlist(dbReadTable(con,”models”)[“model”])
modelsToAdd <- unique(x model[!(x m o d e l [ ! ( x model[!(xmodel %in% modelsInDB)])
for(i in seq_along(modelsToAdd)){
sql <- str_c(“INSERT INTO models (model) VALUES (‘”,
str_replace_all(modelsToAdd[i], “’”, “””),
“’) ;”)
dbGetQuery(con, sql)
}
}
最后,我们进行产品链接的添加和保存。我们需要先查询有哪些产品链接已经存在在数据库中,对于数据库中不存在的产品链接,我们创建SQL语句将其加入到相应的数据库中。其中,unique函数表示“不加入重复行”,str_c函数表示“将字符串进行串联”。

运行程序:
#添加链接
addLinks <- function(x, con){
message(“adding links …”)
linksInDB <- unlist(dbReadTable(con,”links”)[“link”])
linksToAdd <- unique(x link[!(x l i n k [ ! ( x link[!(xlink %in% linksInDB)])
for(i in seq_along(linksToAdd)){
sql <- str_c(“INSERT INTO links (link) VALUES (‘”, linksToAdd[i], “’) ;”)
dbGetQuery(con, sql)
}
}
我们将所有添加信息的函数放在一起组成一个整体的数据存储函数。

运行程序:
# 保存数据的函数
saveInDatabase <- function(x, DBname){
if(grepl(“/dataFull$”,getwd())) setwd(“..”)
sqlite <- dbDriver(“SQLite”)
con <- dbConnect(sqlite, DBname)
defineDatabase(con)
addASINs(x, con)
addProducers(x, con)
addModels(x, con)
addLinks(x, con)
dbDisconnect(con)
}

运用saveInDatabase对phones进行保存,并命名为ebay.db。

运行程序:
saveInDatabase(phones, “ebay.db”)

3.5 数据存储和检查
我们将函数运行一下,测试数据是否真实存在。
# 运行
运行程序:
dbReadTable(con, “phones”)[1:3,]

运行结果:
id asin
1 1 382440661440
2 2 202085839828
3 3 152711279380

运行程序:
dbReadTable(con, “producers”)[1,]

运行结果:
id producer
1 1 Apple

运行程序:
dbReadTable(con, “models”)[1:3,]

运行结果:
id model
1 1 iPhone 7
2 2 iPhone 6s
3 3 iPhone 8 Plus

运行程序:
dbReadTable(con, “links”)[1:3,]

运行结果:
id
1 1
2 2
3 3
link
1 https://www.ebay.com/itm/Apple-iPhone-7-32GB-128GB-256GB-UNLOCKED-All-Colours-1-Year-Warranty/382440661440?epid=225303708&hash=item590b3d61c0:m:mKQepuKr_vqOKemMvtyq7AA
2 https://www.ebay.com/itm/Apple-iPhone-6S-16GB-32GB-64GB-128GB-Gold-Silver-Grey-Rose-UNLOCKED-SIMFREE/202085839828?epid=216278648&hash=item2f0d4133d4:m:mFe_I9iEm-Qws_yA41FxAAA
3 https://www.ebay.com/itm/Apple-iPhone-8-PLUS-64GB-RED-All-Colors-GSM-CDMA-UNLOCKED-BRAND-NEW/152711279380?epid=240377082&hash=item238e4d3314:m:mEoUd0FuGoOoly-MTmJLUIA

通过以上的学习,我们制定了应对各种数据采集和提取问题的解决方案,并把前面的解决方案转化为函数以便重复使用。我们不仅要会利用Rcurl、XML和stringr组件搜索页操控、提取链接和下载页面,在源代码中搜索信息并把Xpath运用到实际问题中。此外,我们还创建了一个SQLite数据库,它能以一致的方式保存数据,并可以用于未来的应用和后续的发展。

手机信息采集 ——基于ebay网站Apple手机案例分析相关推荐

  1. 崔华 oracle简历,2013数据库大会:崔华-基于Oracle的SQL优化案例分析

    2013数据库大会:崔华-基于Oracle的SQL优化案例分析 崔华的新书即将出版,其数据库大会上的演讲也非常精彩,他的新书十分值得期待. 2013年中国数据库技术大会第二天的"Oracle ...

  2. 电子商务网站商品推荐案例分析

    本案例的主要目的是通过分析用户和网站数据,使用数据挖掘技术,分析老客户忠诚度下降的原因. 建立客户忠诚度模型,提高其忠诚度. 一.分析方法和过程 数据来源:客户信息.交易信息分别存放在网站数据库的客户 ...

  3. 农夫山泉基于SAP SMP移动应用案例分析

    移动化时代的到来,企业都选择了紧跟时代的潮流,作为国内快消品行业的领先者,农夫山泉也已经将移动化的能量发挥到了极致,虽然企业成立的时间不如其他竞争对手,但是在新技术方面的应用确实领先不少. ▲农夫山泉 ...

  4. 大型网站典型故障案例分析

    写日志也会引发故障 故障现象:某应用服务器集群发布后不久就出现多台服务器相继报警,硬盘可用空间低于警戒值,并且很快有服务器宕机,登录到线上服务器,发现log文件夹里的文件迅速增加,不断消耗磁盘空间. ...

  5. 基于R语言的Kaggle案例分析-泰坦尼克号

    背景 泰坦尼克号由位于北爱尔兰贝尔法斯特的哈兰·沃尔夫船厂兴建,是当时最大的客运轮船,由于其规模相当一艘现代航空母舰,因而号称"上帝也沉没不了的巨型邮轮".在泰坦尼克号的处女航中, ...

  6. 演出票务网站的SEO案例分析

    通过SEO,票务网站分到了节前票务市场的一杯羹 一.网站定位分析 中国票务在线的火车票频道(http://train.piao.com.cn)定位在中国专业的二手火车票交易服务平台.为网民提供火车票转 ...

  7. 基于百度地图记录运动轨迹案例分析与实现

    目录## 一.下载百度地图SDK 二. 工程配置 1. 新建Xcode工程 2. 获取Bundle Identifie 3. 申请key 4. 导入框架配置工程 第一步: 引入BaiduMapAPI. ...

  8. 读书笔记之 大型网站技术架构(核心原理与案例分析)

    前言 坚持看了十几天的书,终于完成了毕业后第一次静下心来,利用业务时间看书并做笔记的成就了.废话不多说,这回看的是一直很膜拜的李智慧大神写的大型网站技术架构-核心原理与案例分析. 简短的读后感 极其推 ...

  9. 大型网站技术架构:核心原理与案例分析pdf

    下载地址:网盘下载 编辑推荐 编辑 本书作者是阿里巴巴网站构建的亲历者,拥有核心技术部门的一线工作经验,直接体验了大型网站构建与发展过程中的种种生与死,蜕与变,见证了一个网站架构从幼稚走向成熟稳定的历 ...

最新文章

  1. 使用request实现网站中的注册功能
  2. java 打印 排序 数字塔_求助,用循环方法输出以下数字塔
  3. 实录 | DSTC 8“基于Schema的对话状态追踪”竞赛冠军方案解读
  4. ABP源码分析二十五:EventBus
  5. 在职场中,什么是职场大忌?
  6. 一. python的collections模块
  7. Win7 局域网内简单共享的设置
  8. Winform打包-NSIS 检测.NetFramework版本(亲测可用)
  9. ActiveX控件注册的几种方法
  10. CAD布局图纸导出为模型图纸
  11. 可能是最简单暴力的卸载工具Geek Uninstaller
  12. java从键盘输入若干学生的成绩_初学Java3:数组-从键盘录入若干学生的成绩,计算平均值,最大值,最小值...
  13. 店宝宝:10年前的小游戏集体复活
  14. 完成10亿元D轮融资,易快报成费控SaaS独角兽?
  15. git 命令git 地址_5个高级Git命令来启动您的Git游戏
  16. 关于跨境电商你了解多少!我们应该怎么做跨境电商?(中)
  17. 立创EDA之导出BOM
  18. 原创 | GIS国产化除了软件还有什么
  19. win7x64新进程画面均无显示一例分析——从内核态到用户态,从x64到wow64,从汇编到托管
  20. Keras深度学习实战(34)——构建聊天机器人

热门文章

  1. 【Hbu数据库】第七周 数据库完整性 存储过程和函数
  2. 《 HTML5 》— HTML5页面元素及属性
  3. 四川大学考研真题 || 信息资源管理导论(二)
  4. 重构实践:基于腾讯云Elasticsearch搭建QQ邮箱全文检索
  5. PEP代码规范简单总结
  6. Junit-对涉及数据库操作的服务进行单元测试
  7. Tomcat 多实例安装 发布3个java项目: 8080 8081 8082
  8. 关于 AlphaBlend 和 32bpp 的反锯齿图标
  9. (3分钟速通)Visual Odometry的特征点法和直接法
  10. Python破解滑动验证码(极验/无背景图)