• R语言
  • 抓取网页数据时遇到的问题。

先简单说一下做这个抓取的思路:

1、用DD函数抓取商品名称;

2、抓取列表页“http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index”=i,i=1,2,……中的全部商品的url(大概一个列表页有25个url)

3、用DD函数解析i个列表页上抓取出来的25*i个url的商品名称,最后写到数据表df中。

在抓取dangdang数据时,遇到几个问题,请大侠指导一下:

1、做循环抓取i个列表页时,出现以下错误:

错误: XML content does not seem to be XML, nor to identify a file name 'http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=1

http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=2

http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=3

http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=4'

应该是无法解析吧,怎么能加一个判断,直到解析页面后再继续抓取这个列表页中商品链接呢?

2、最后得到的数据表df好像格式上有些问题。

脚本如下:

<br />
library(XML)<br />
DD<-function(url){<br />
    url <- htmlParse(url,encoding="GBK")<br />
    name <- getNodeSet(url,"//div[@class='head'][@name='Title_pub']//h1")<br />
    name_text_tmp<-xmlValue(name[[1]])<br />
    name_text_tmp<-iconv(name_text_tmp,"UTF-8","gbk")<br />
return(name_text_tmp)<br />
}</p>
<p>i <- seq(1,4,1)<br />
for(url_i  in i){<br />
  url_i <- paste("http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=",i,sep = "")<br />
  url_i <- htmlParse(url_i,encoding="GBK")<br />
  nodes_i <- getNodeSet(url_i,"//div[@class='listitem pic']//a[@href]")<br />
  Product_linkings_i <- sapply(nodes_i, function(x) xmlGetAttr(x, "href"))<br />
  Sys.sleep(3)<br />
  }<br />
df <- list()<br />
for(i in Product_linkings_i) df[i] <- DD(i)<br />
r <- do.call(rbind,df)<br />
</p>

> i <- seq(1,4,1)<br />
> for(url_i  in i) {print(url_i)}


[1] 1

[1] 2

[1] 3

[1] 4
</p>

回复 第1楼 的 danny_liu:

第二个问题解决了,用lappy效率更高一些

df <- list()<br />
system.time(df <-lapply(Product_linkings_i, function(x) DD(x)))<br />
用户  系统  流逝<br />
 1.56  0.06 89.64 </p>
<p>system.time(for(i in Product_linkings_i) df[i] <- DD(i))<br />
  用户   系统   流逝<br />
  1.72   0.04 102.66<br />
</p>

还请各位大侠在第一个问题上指教一下。

程序本身的思路没问题。循环语句有点混乱。是这个意思吧?

<br />
i <- seq(1,4,1)<br />
for(url_id  in i){<br />
  url_i <- paste("http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=",url_id,sep = "")<br />
  url_i <- htmlParse(url_i,encoding="GBK")<br />
  nodes_i <- getNodeSet(url_i,"//div[@class='listitem pic']//a[@href]")<br />
  Product_linkings_i <- sapply(nodes_i, function(x) xmlGetAttr(x, "href"))<br />
  Sys.sleep(3)<br />
  }<br />
</p>

回复 第4楼 的 iamstomach:你好。

我的问题是,现在共有i(i <- seq(1,4,1))个列表页http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=i,每个列表中有n个网址Product_linkings,我想要做的是把i*n个网址全部扒下来,而且还想做一个判断,当网络有问题的时候,不能读取某一个列表页时,加上一个循环直至抓取出来为止。

不知道你说网络有问题会输出什么样的error。试试try()函数,try()函数也能让你抓网页的工作一直进行下去,而不在中途停止。

<br />
i <- seq(1,4,1)<br />
for(url_id  in i){<br />
  url <- paste("http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=",url_id,sep = "")<br />
  url_value <- try(htmlParse(url,encoding="GBK"), F)<br />
  while ( expr ){<br />
    url_value <- try(htmlParse(url,encoding="GBK"), F)<br />
  }<br />
}<br />


while条件能够实现你说的那个循环直到抓取出来为止,不过不知道你的error是啥样的,所以while语句的条件我用expr代替了。参考下面的例子:
<br />
x <- list(10, 20, "a", "b")<br />
z <- list(0)<br />
y <- list(0)<br />
for (i in 1:length(x)){<br />
   z[[i]] <- log(x[[i]])<br />
}<br />
# 提示错误,停止运行<br />
# 错误于log(x[[i]]) : 数学函数中用了非数值参数<br />
for (i in 1:length(x)){<br />
  y[[i]] <- try(log(x[[i]]), F)<br />
  while (y[[i]][1] == "Error in log(x[[i]]) : 数学函数中用了非数值参数\n"){<br />
    y[[i]] = "Bingo"<br />
  }<br />
}<br />
# 提示错误,继续运行<br />
# Error in log(x[[i]]) : 数学函数中用了非数值参数<br />
# Error in log(x[[i]]) : 数学函数中用了非数值参数<br />
z<br />
# [[1]]<br />
# [1] 2.302585<br />
#<br />
# [[2]]<br />
# [1] 2.995732<br />
y<br />
# [[1]]<br />
# [1] 2.302585<br />
#<br />
# [[2]]<br />
# [1] 2.995732<br />
#<br />
# [[3]]<br />
# [1] "Bingo"<br />
#<br />
# [[4]]<br />
# [1] "Bingo"<br />
</p>

回复 第6楼 的 iamstomach:你好,非常感谢[s:13]

我先用try()尝试了一下,出来了一部分结果。

<br />
i <- seq(1,10,1)<br />
for(url_id  in 1:length(i)){<br />
  url_i <- paste("http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=",url_id,sep = "")<br />
  url_value_i <- try(htmlParse(url_i,encoding="GBK"),F)<br />
  nodes_i <- getNodeSet(url_value_i,"//div[@class='listitem pic']//a[@href]")<br />
  Product_linkings_i <- sapply(nodes_i, function(x) xmlGetAttr(x, "href"))<br />
  Sys.sleep(rnorm(1,3,1))<br />
  print(Product_linkings_i)<br />
}</p>
<p>#Error : failed to load HTTP resource<br />
#<br />
#错误于UseMethod("xpathApply") :<br />
#  "xpathApply"没有适用于"try-error"目标对象的方法<br />


然后用while()后,还是出现同样的错误,不知道是哪儿写错了,还请指导一下,谢谢。
<br />
  while(url_value_i == "Error : failed to load HTTP resource\n" ){<br />
    url_value_i <- try(htmlParse(url_i,encoding="GBK"), F)<br />
  }</p>
<p>#Error : failed to load HTTP resource<br />
#<br />
#错误于UseMethod("xpathApply") :<br />
#  "xpathApply"没有适用于"try-error"目标对象的方法<br />
</p>

回复 第7楼 的 danny_liu:换个思路,试试看class()吧

<br />
i <- seq(1,10,1)<br />
for(url_id  in 1:length(i)){<br />
  url_i <- paste("http://category.dangdang.com/all/?category_path=01.00.00.00.00.00&page_index=",url_id,sep = "")<br />
  url_value_i <- try(htmlParse(url_i,encoding="GBK"),F)<br />
  j=0<br />
  while (!mode(url_value_i) == "externalptr") {<br />
    url_value_i <- try(htmlParse(url_i,encoding="GBK"), F)<br />
    j = j+1<br />
    print(paste("redo", j))<br />
  }<br />
  print(url_i)<br />
}<br />
</p>

回复 第8楼 的 iamstomach:Bingo,Million thanks[s:13]

还有一个小问题,如何能把抓取出来的url_i(i=1,……10),放在一个data.frame里呢?

回复 第9楼 的 danny_liu:我以前的笨方法是

<br />
url_all <- character(0)<br />
for (){<br />
  url_all <- rbind(url_all, url_i)<br />
}<br />


这样可以依次叠加下来了
</p>

回复 第10楼 的 iamstomach:非常感谢[s:13]有否能留下邮箱,交流一下。

回复 第10楼 的 iamstomach:

得到的结果好像不太对。

<br />
url_all <- list()<br />
for (i in seq(1,4,1)){<br />
  url_all <- rbind(url_all, url_i)<br />
}<br />
</p>

回复 第12楼 的 danny_liu:在合并前用as.data.frame稍微调整下格式。henji03@163.com