作者 SAURAV KAUSHIK
译者 钱亦欣
引言
网上的数据和信息无穷无尽,如今人人都用百度谷歌来作为获取知识,了解新鲜事物的首要信息源。所有的这些网上的信息都是直接可得的,而为了满足日益增长的数据需求,我坚信网络数据爬取已经是每个数据科学家的必备技能了。在本文的帮助下,你将会突破网络爬虫的技术壁垒,实现从不会到会。
大部分网上呈现的信息都是以非结构化的格式存储(html)且不提供直接的下载链接,因此,我们需要学习一些知识和经验来获取这些数据。
本文我将带你领略利用R做网络数据采集的全过程,通读文章后你将掌握如何来使用因特网上各位数据的技能。
目录
什么是网络数据爬取
为什么需要爬取数据
数据爬取方法
前提条件
使用R爬取网页
分析从网页爬取的数据
1. 什么是网络数据爬取
网络爬虫是讲呈现在网页上以非结构格式(html)存储的数据转化为结构化数据的技术,该技术非常简单易用。
几乎所有的主流编程语言都提供了网络数据爬取的实现方式,本文我们会用R来爬取IMDB上2016年最热门电影的一些特征。
我们将采集2016年度最热门电影的若干特征,同时我们也会遇到网页代码不一致的问题并将其解决。这是在做网络爬虫时最常遇到的问题之一。
如果你更喜欢用python变成,我建议你看这篇指南来学习如何用python做爬虫。
2. 为什么需要爬取数据
我确信你现在肯定在问“为什么需要爬取数据”,正如前文所述,爬取网页数据极有可能。(译者注:原文如此,我没看懂这个设问的逻辑)
为了提供一些使用的知识,我们将会爬取IMDB的数据,同时,利用爬虫你还可以:
爬取电影评分来构建推荐系统
爬取维基百科等信源的文本作为训练预料来构建深度学习模型以实现主体识别等功能
爬取有标签的图像(从Google,Flickr等网站)来训练图像分类模型
爬取社交媒体数据(Facebook 和 Twitter 等)做情感分析,观点挖掘等
爬取电商的用户评论和反馈(从Amazon,Flipkart等)
3. 数据爬取方法
网络数据抓取的方式有很多,常用的有:
人工复制粘贴:这是采集数据的缓慢但有效的方式,相关的工作人员会自行分析并把数据复制到本地。
文本模式匹配:另一种简单有效的方法是利用编程语言中的正则表达式来匹配固定模式的文本,在这里你可以学到关于正则表达式的更多内容。
使用API:诸如Facebook,Twitter和Linkedin一类的许多网站都提供了公共或者私人的API,它们提供了标准化的代码供用户请求规定格式的数据。
DOM解析:程序可以使用浏览器来获取客户端脚本生成的动态内容。基于这些程序可以获得的页面来使用DOM树来解析网页也是可行的办法,
我们会使用DOM解析的方式来获取数据,并基于网页的CSS选择器来寻找含有所需信息的网页部分。但在开始之前,我们必须满足一些前提条件。
4. 前提条件
利用R实现网络爬虫的前提条件有两大块:
要写R语言爬虫,你对R必须有一定了解。如果你还是个新手,我强烈建议参照这个学习路径 来学习。本文将使用“Hadley Wickham(Hadley我爱你!!!)”开发的“rvest”包来实现爬虫。你可以从这里获得这个包的文档。如果你没有安装这个包,请执行以下代码。
install.packages('rvest')
除此之外,HTML,CSS的相关知识也很重要。学习他们的有一个很好的资源。我见识过不少对HTML和CSS缺乏了解的数据科学家,因此我们将使用名为Selector Gadget的开源软件来更高效地实现抓取。你可以在这里下载这个工具包。请确保你的浏览器已经安装了这个插件(推荐用chrome浏览器),并且能正常使用。(译者注:chrome中的css viewer 和 xpath helper 也是神器。)
使用这个插件你可以通过点击任一网页中你需要的数据就能获得相应的标签。你也可以学习HTML和CSS的知识并且手动实现这一过程。而且,为了更深入地了解网络爬取这一艺术,我很推荐你学习下HTML和CSS来了解其背后的机理。
5. 使用R爬取网页
现在让我们开始爬取IMDB上2016年度最流行的100部故事片,你可以在这里查看相关信息。
# 加载包
library('rvest')
# 指定要爬取的url
url <- 'http://www.imdb.com/search/title?
count=100&release_date=2016,2016&title_type=feature'
# 从网页读取html代码
webpage <- read_html(url)
现在,让我们爬取网页上的这些数据:
Rank:从1到100,代表排名
Title:故事片的标题
Description:电影内容简介
Runtime: 电影时长
Genre: 电影类型
Rating: IMDB提供的评级
Metascore: IMDB上该电影的评分
Votes: 电影的好评度
Gross_Earning_in_Mil: 电影总票房(百万)
Director: 影片的总导演,如果有多位,取第一个
Actor: 影片的主演,如果有多位,取第一个
这是页面的截图
Step 1: 爬取的第一步是使用 selector gadget获得排名的CSS选择器。你可以点击浏览器中的插件图标并用光标点击排名的区域。
要确保所有的排名都被选择了,你也可以再次点击选中区域来取消选择,最终只有高亮的那些部分会被爬取。
Step 2: 一旦你已经选择了正确的区域,你需要把在底部中心显示的相应的CSS选择器复制下来。
Step 3: 只要CSS选择器包含排名,你就能用几行简单的代码来获取所有的排名了:
# 用CSS选择器获取排名部分
rank_data_html <- html_nodes(webpage,'.text-primary')
# 把排名转换为文本
rank_data <- html_text(rank_data_html)
# 检查一下数据
head(rank_data)
[1] "1." "2." "3." "4." "5." "6."
Step 4: 获取数据之后,请确保他们被你所需的格式存储,我会把排名处理成数值型。
# 数据预处理:把排名转换为数值型
rank_data<-as.numeric(rank_data)
# 再检查一遍
head(rank_data)
[1] 1 2 3 4 5 6
Step 5: 现在你可以清空选择部分并开始选择电影标题了,你可以看见所有的标题都被选择了,你依据个人需要做一些增删。
Step 6: 正如从前,再次复制CSS选择器并用下列代码爬取标题。
# 爬取标题
title_data_html <- html_nodes(webpage,'.lister-item-header a')
# 转换为文本
title_data <- html_text(title_data_html)
# 检查一下
head(title_data)
[1] "Sing" "Moana" "Moonlight" "Hacksaw Ridge"
[5] "Passengers" "Trolls"
Step 7: 下列代码会爬取剩余的数据– Description, Runtime, Genre, Rating, Metascore, Votes, Gross_Earning_in_Mil , Director and Actor data.
# 爬取描述
description_data_html <- html_nodes(webpage,'.ratings-bar+ .text-muted')
# 转为文本
description_data <- html_text(description_data_html)
# 检查一下
head(description_data)
[1] "\nIn a city of humanoid animals, a hustling theater impresario's attempt to save his theater with a singing competition becomes grander than he anticipates even as its finalists' find that their lives will never be the same."
[2] "\nIn Ancient Polynesia, when a terrible curse incurred by the Demigod Maui reaches an impetuous Chieftain's daughter's island, she answers the Ocean's call to seek out the Demigod to set things right."
[3] "\nA chronicle of the childhood, adolescence and burgeoning adulthood of a young, African-American, gay man growing up in a rough neighborhood of Miami."
[4] "\nWWII American Army Medic Desmond T. Doss, who served during the Battle of Okinawa, refuses to kill people, and becomes the first man in American history to receive the Medal of Honor without firing a shot."
[5] "\nA spacecraft traveling to a distant colony planet and transporting thousands of people has a malfunction in its sleep chambers. As a result, two passengers are awakened 90 years early."
[6] "\nAfter the Bergens invade Troll Village, Poppy, the happiest Troll ever born, and the curmudgeonly Branch set off on a journey to rescue her friends.
# 移除 '\n'
description_data<-gsub("\n","",description_data)
# 再检查一下
head(description_data)
[1] "In a city of humanoid animals, a hustling theater impresario's attempt to save his theater with a singing competition becomes grander than he anticipates even as its finalists' find that their lives will never be the same."
[2] "In Ancient Polynesia, when a terrible curse incurred by the Demigod Maui reaches an impetuous Chieftain's daughter's island, she answers the Ocean's call to seek out the Demigod to set things right."
[3] "A chronicle of the childhood, adolescence and burgeoning adulthood of a young, African-American, gay man growing up in a rough neighborhood of Miami."
[4] "WWII American Army Medic Desmond T. Doss, who served during the Battle of Okinawa, refuses to kill people, and becomes the first man in American history to receive the Medal of Honor without firing a shot."
[5] "A spacecraft traveling to a distant colony planet and transporting thousands of people has a malfunction in its sleep chambers. As a result, two passengers are awakened 90 years early."
[6] "After the Bergens invade Troll Village, Poppy, the happiest Troll ever born, and the curmudgeonly Branch set off on a journey to rescue her friends."
# 爬取runtime section
runtime_data_html <- html_nodes(webpage,'.text-muted .runtime')
# 转为文本
runtime_data <- html_text(runtime_data_html)
# 检查一下
head(runtime_data)
[1] "108 min" "107 min" "111 min" "139 min" "116 min" "92 min"
# 数据预处理: 去除“min”并把数字转换为数值型
runtime_data <- gsub(" min","",runtime_data)
runtime_data <- as.numeric(runtime_data)
# 再检查一下
head(rank_data)
[1] 1 2 3 4 5 6
# 爬取genre
genre_data_html <- html_nodes(webpage,'.genre')
# 转为文本
genre_data <- html_text(genre_data_html)
# 检查一下
head(genre_data)
[1] "\nAnimation, Comedy, Family "
[2] "\nAnimation, Adventure, Comedy "
[3] "\nDrama "
[4] "\nBiography, Drama, History "
[5] "\nAdventure, Drama, Romance "
[6] "\nAnimation, Adventure, Comedy "
# 去除“\n”
genre_data<-gsub("\n","",genre_data)
# 去除多余空格
genre_data<-gsub(" ","",genre_data)
# 每部电影只保留第一种类型
genre_data<-gsub(",.*","",genre_data)
# 转化为因子
genre_data<-as.factor(genre_data)
# 再检查一下
head(genre_data)
[1] Animation Animation Drama Biography Adventure Animation
10 Levels: Action Adventure Animation Biography Comedy Crime Drama ... Thriller
# 爬取IMDB rating
rating_data_html <- html_nodes(webpage,'.ratings-imdb-rating strong')
# 转为文本
rating_data <- html_text(rating_data_html)
# 检查一下
head(rating_data)
[1] "7.2" "7.7" "7.6" "8.2" "7.0" "6.5"
# 转为数值型
rating_data<-as.numeric(rating_data)
# 再检查一下
head(rating_data)
[1] 7.2 7.7 7.6 8.2 7.0 6.5
# 爬取votes section
votes_data_html <- html_nodes(webpage,'.sort-num_votes-visible span:nth-child(2)')
# 转为文本
votes_data <- html_text(votes_data_html)
# 检查一下
head(votes_data)
[1] "40,603" "91,333" "112,609" "177,229" "148,467" "32,497"
# 移除“,”
votes_data<-gsub(",", "", votes_data)
# 转为数值型
votes_data<-as.numeric(votes_data)
# 再检查一下
head(votes_data)
[1] 40603 91333 112609 177229 148467 32497
# 爬取directors section
directors_data_html <- html_nodes(webpage,'.text-muted+ p a:nth-child(1)')
# 转为文本
directors_data <- html_text(directors_data_html)
# 检查一下
head(directors_data)
[1] "Christophe Lourdelet" "Ron Clements" "Barry Jenkins"
[4] "Mel Gibson" "Morten Tyldum" "Walt Dohrn"
# 转为因子
directors_data<-as.factor(directors_data)
# 爬取actors section
actors_data_html <- html_nodes(webpage,'.lister-item-content .ghost+ a')
# 转为文本
actors_data <- html_text(actors_data_html)
# 检查一下
head(actors_data)
[1] "Matthew McConaughey" "Auli'i Cravalho" "Mahershala Ali"
[4] "Andrew Garfield" "Jennifer Lawrence" "Anna Kendrick"
# 转为因子
actors_data<-as.factor(actors_data)
我时爬Metascore时遇到问题,我希望你能仔细看看。
# 爬取metascore section
metascore_data_html <- html_nodes(webpage,'.metascore')
# 转为文本
metascore_data <- html_text(metascore_data_html)
# 检查一下
head(metascore_data)
[1] "59 " "81 " "99 " "71 " "41 "
[6] "56 "
# 去除多余空格
metascore_data<-gsub(" ","",metascore_data)
# 检查metascore data的长度
length(metascore_data)
[1] 96
Step 8: meta score只有96个数据,可我们却爬取了100部电影。这个问题产生的原型是由4部电影没有Metascore数据。
Step 9: 这是爬取所有网页都会遇到的常见问题,如果我们只是简单地用NA来填充这四个缺失值,它会自动填充第97到100部电影。通过一些可视化检查,我们发缺失matascore的是第39,73,80和89部电影。我用下面的函数来解决这个问题。
for (i in c(39,73,80,89)){
a <- metascore_data[1:(i-1)]
b<-metascore_data[i:length(metascore_data)]
metascore_data <- append(a, list("NA"))
metascore_data <- append(metascore_data, b)
}
# 转换为数值型
metascore_data <- as.numeric(metascore_data)
# 再次检查下长度
length(metascore_data)
[1] 100
# 看看描述性统计量
summary(metascore_data)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
23.00 47.00 60.00 60.22 74.00 99.00 4
Step 10: 同样的问题也会发生在Gross变量上,我用同样的方式来解决。
# 爬取revenue section
gross_data_html <- html_nodes(webpage,'.ghost~ .text-muted+ span')
# 转为文本
gross_data <- html_text(gross_data_html)
# 检查一下
head(gross_data)
[1] "$269.36M" "$248.04M" "$27.50M" "$67.12M" "$99.47M" "$153.67M"
# 去除'$' 和 'M' 标记
gross_data <- gsub("M", "", gross_data)
gross_data <- substring(gross_data, 2, 6)
# 检查长度
length(gross_data)
[1] 86
# 填充缺失值
for (i in c(17,39,49,52,57,64,66,73,76,77,80,87,88,89)){
a <- gross_data[1:(i-1)]
b <- gross_data[i:length(gross_data)]
gross_data <- append(a, list("NA"))
gross_data <- append(gross_data, b)
}
# 转为数值
gross_data<-as.numeric(gross_data)
# 再次检车长度
length(gross_data)
[1] 100
summary(gross_data)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
0.08 15.52 54.69 96.91 119.50 530.70 14
Step 11: .我们已经成功爬取了100部电影的11个特征,让我们创建一个数据框并看看结构。
# 合并所有list来创建一个数据框
movies_df <- data.frame(
Rank = rank_data,
Title = title_data,
Description = description_data,
Runtime = runtime_data,
Genre = genre_data,
Rating = rating_data,
Metascore = metascore_data,
Votes = votes_data,
Gross_Earning_in_Mil = gross_data,
Director = directors_data,
Actor = actors_data
)
# 查看数据框结构
str(movies_df)
'data.frame' : 100 obs. of 11 variables:
$ Rank : num 1 2 3 4 5 6 7 8 9 10 ...
$ Title : Factor w/ 99 levels "10 Cloverfield Lane",..: 66 53 54 32 58 93 8 43 97 7 ...
$ Description : Factor w/ 100 levels "19-year-old Billy Lynn is brought home for a victory tour after a harrowing Iraq battle. Through flashbacks the film shows what"| __truncated__,..: 57 59 3 100 21 33 90 14 13 97 ...
$ Runtime : num 108 107 111 139 116 92 115 128 111 116 ...
$ Genre : Factor w/ 10 levels "Action","Adventure",..: 3 3 7 4 2 3 1 5 5 7 ...
$ Rating : num 7.2 7.7 7.6 8.2 7 6.5 6.1 8.4 6.3 8 ...
$ Metascore : num 59 81 99 71 41 56 36 93 39 81 ...
$ Votes : num 40603 91333 112609 177229 148467 ...
$ Gross_Earning_in_Mil: num 269.3 248 27.5 67.1 99.5 ...
$ Director : Factor w/ 98 levels "Andrew Stanton",..: 17 80 9 64 67 95 56 19 49 28 ...
$ Actor : Factor w/ 86 levels "Aaron Eckhart",..: 59 7 56 5 42 6 64 71 86 3 ...
现在2016年上映的最流行的100部故事片在IMDB上的数据已经爬取成功了!
6. 分析从网页爬取的数据
爬取好数据后,你们队数据进行一些分析与推断,训练一些机器学习模型。我在上面这个数据集的基础上做了一些有趣的可视化来回答下面的问题。
library('ggplot2')
qplot(data = movies_df,Runtime,fill = Genre,bins = 30)
**Question 1: ** 那个类型的电影市场最长?
ggplot(movies_df,aes(x=Runtime,y=Rating))+
geom_point(aes(size=Votes,col=Genre))
**Question 2: ** 市场130-160分钟的电影里,哪一类型东西好评率最高?
ggplot(movies_df,aes(x=Runtime,y=Gross_Earning_in_Mil))+
geom_point(aes(size=Rating,col=Genre))
**Question 3: ** 100-120分钟的电影中,哪类作品的票房成绩最好
结语
我相信本文会让你对利用R爬取网页有一定了解,你对采集数据过程中可能遇到的问题也有所涉猎了。由于网页上的大部分数据是非结构化的,爬虫真的是非常重要的一项技能。
原文链接:https://www.analyticsvidhya.com/blog/2017/03/beginners-guide-on-web-scraping-in-r-using-rvest-with-hands-on-knowledge/
说在前面 如果读过了上一篇文章,应该对Rcurl和XML包进行爬虫有了一定得了解。实际上,这个组合虽然功能强大,但是经常会出一点意想不到的小问题。这篇文章我将介绍更便捷的Rvest包真正的快速爬取想要的数据。
主要内容
还是以上篇文章的豆瓣图书 Top250为例,我们只需要以下几行代码就可以实现与上文一样的效果:
library(rvest)
web<-read_html("https://book.douban.com/top250?icn=index-book250-all",encoding="UTF-8")
position<-web %>% html_nodes("p.pl") %>% html_text()
逐行解读一下。
第一行是加载Rvest包。
第二行是用read_html函数读取网页信息(类似Rcurl里的getURL),在这个函数里只需写清楚网址和编码(一般就是UTF-8)即可。
第三行是获取节点信息。用%>%符号进行层级划分。web就是之前存储网页信息的变量,所以我们从这里开始,然后html_nodes()函数获取网页里的相应节点。在下面代码里我简单的重现了原网页里的一个层级结构。可以看到,实际上我们要爬取的信息在25个class属性为pl的
标签里的文本。
[清] 曹雪芹 著 / 人民文学出版社 / 1996-12 / 59.70元
而对于这样的结构,在htmlnodes()函数里的写法就是简单的 "p.pl",其中“.”表示class属性的值,如果是id属性则用“#”,如果大家学过CSS选择器就很好理解了,是完全一致的。
最后我们用html_text()函数表示获取文本信息,否则返回的是整个
标签。总体上用以下一行代码就可以实现:
position<-web %>% html_nodes("p.pl") %>% html_text()
比较与XML获取节点的方法(如下行代码),其实二者是异曲同工的,只不过将“/”分隔换为了“%>%”,同时个别写法有些许调整。
node<-getNodeSet(pagetree, "//p[@class='pl']/text()")
最终如果我们打印出这个变量的内容,就会发现和上篇文章中的爬取内容是一致的:
> position
[1] "[美] 卡勒德·胡赛尼 / 李继宏 / 上海人民出版社 / 2006-5 / 29.00元"
[2] "[法] 圣埃克苏佩里 / 马振聘 / 人民文学出版社 / 2003-8 / 22.00元"
[3] "钱锺书 / 人民文学出版社 / 1991-2 / 19.00"
[4] "余华 / 南海出版公司 / 1998-5 / 12.00元"
[5] "[日] 东野圭吾 / 刘姿君 / 南海出版公司 / 2008-9 / 29.80元"
[6] "[日] 村上春树 / 林少华 / 上海译文出版社 / 2001-2 / 18.80元"
[7] "(日)东野圭吾 / 李盈春 / 南海出版公司 / 2014-5 / 39.50元"
[8] "[捷克] 米兰·昆德拉 / 许钧 / 上海译文出版社 / 2003-7 / 23.00元"
[9] "[清] 曹雪芹 著 / 人民文学出版社 / 1996-12 / 59.70元"
[10] "刘慈欣 / 重庆出版社 / 2008-1 / 23.00"
[11] "郭敬明 / 春风文艺出版社 / 2003-11 / 20.00元"
[12] "[美] 丹·布朗 / 朱振武 / 上海人民出版社 / 2004-2 / 28.00元"
[13] "[日] 东野圭吾 / 刘子倩 / 南海出版公司 / 2008-9 / 28.00"
[14] "韩寒 / 国际文化出版公司 / 2010-9 / 25.00元"
[15] "柴静 / 广西师范大学出版社 / 2013-1-1 / 39.80元"
[16] "顾漫 / 朝华出版社 / 2007-4 / 15.00元"
[17] "[英] 夏洛蒂·勃朗特 / 世界图书出版公司 / 2003-11 / 18.00元"
[18] "路遥 / 人民文学出版社 / 2005-1 / 64.00元"
[19] "[英] J. K. 罗琳 / 苏农 / 人民文学出版社 / 2000-9 / 19.50元"
[20] "[哥伦比亚] 加西亚·马尔克斯 / 范晔 / 南海出版公司 / 2011-6 / 39.50元"
[21] "[美国] 玛格丽特·米切尔 / 李美华 / 译林出版社 / 2000-9 / 40.00元"
[22] "李可 / 陕西师范大学出版社 / 2007-9 / 26.00元"
[23] "韩寒 / 作家出版社 / 2000-5 / 16.00"
[24] "刘瑜 / 上海三联书店 / 2010-1 / 25.00元"
[25] "张爱玲 / 花城出版社 / 1997-3-1 / 11.00"
想要学习更多,我们可以在Rstudio里的命令行输入如下代码查询html_nodes()函数的相关用法:
Rvest这个包的说明文档里给出了一些其他例子:
ateam <- read_html("http://www.boxofficemojo.com/movies/?id=ateam.htm")
ateam %>% html_nodes("center") %>% html_nodes("td")
ateam %>% html_nodes("center") %>% html_nodes("font")
library(magrittr)
ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% `[[`(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% `[`(1:2) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% extract(1:2) %>% html_nodes("img")
下面也一并讲解一下:
ateam <- read_html("http://www.boxofficemojo.com/movies/?id=ateam.htm")
首先,所有的例子都是基于同一个网站,我们把这个网站存储在ateam变量里。
然后下面两行代码分别获取了ateam这个网页里
标签里的全部内容和标签里的全部内容
ateam %>% html_nodes("center") %>% html_nodes("td")
ateam %>% html_nodes("center") %>% html_nodes("font")
运行结果如下,可见
标签下有7个标签,一个标签:
{xml_nodeset (7)}
[1] \n Domestic Total Gross: $77,222, ...
[2] Distributor: Fox Release Date: Genre: Action
[5] Runtime: 1 hrs. 57 min.
[6] MPAA Rating: PG-13
[7] Production Budget: $110 million
{xml_nodeset (1)}
[1] Domestic Total Gross: $77,222,099
接着官方例子中还给出了获取特定序位的html标签的方法,用到了magrittr包里的extract2函数:
library(magrittr)
ateam %>% html_nodes("table") %>% extract2(1) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% `[[`(1) %>% html_nodes("img")
上面两行代码都可以获得该网页中第一个
标签(由extract2(1)或`[[`(1)获取)中的所有 标签里的内容,运行结果如下:
{xml_nodeset (6)}
[1]
[5]
[6]
同理我们也可以获得网页里前两个
标签储存的所有 标签里的内容:
ateam %>% html_nodes("table") %>% `[`(1:2) %>% html_nodes("img")
ateam %>% html_nodes("table") %>% extract(1:2) %>% html_nodes("img")
本篇文章就到此为止了,之后我将继续讲解关于正则以及R中stringr包的相关内容,对获取的字符串进行进一步的处理操作。
结语
更多内容请关注我的专栏:R语言与数据挖掘 - 知乎专栏
或关注我本人知乎主页:温如
R语言学习:使用rvest包抓取网页数据
无鱼二饼 关注
2017.03.10 23:15* 字数 634 阅读 3636
rvest是R语言一个用来做网页数据抓取的包,包的介绍就是“更容易地收割(抓取)网页”。其中html_nodes()函数查找标签的功能非常好用。以抓取天猫搜索结果页的宝贝数据为例说明rvest的使用。
分析网页
打开天猫,按F12键打开浏览器的开发工具。个人用的火狐,谁让Chrom不支持linux了,唉。不过还是chrome好用啊。其他浏览器都有类似的功能。
随便搜索个啥,比如核弹,我草还真出结果了!
接下来,在浏览器的开发工具"查看器"中查看网页的源码。或者按一下CTRL+SHIFT+C,选择任意宝贝。可以看到宝贝的图片、月销量等数据都是包含在...
块中的。
打开该div块,哈哈,咱们需要的商品图片、链接、月销量、价格,以及商户名称等,都可以在里面找到了。话说,猫爹其实挺开放的,没有做太多限制,不然想抓这些数据就麻烦了。
接下来启动R,以下是用rvest包抓取宝贝数据的过程
安装rvest包 install.packages("rvest")
加载rvest包 library(rvest)
保存搜索链接到对象gurl,链接的拼接方式挺有规律的 gurl <- "https://list.tmall.com/search_product.htm?q=%C9%AD%B1%C8%B0%C2&type=p&vmarket=&spm=875.7931836%2FB.a2227oh.d100&from=mallfp..pc_1_searchbutton"
抓取数据保存到对象md中
%>%是管道操作符,意思是把左边的操作结果作为参数传递给右边的命令
div.product-iWrap 是CSS选择器的语法,即是 div class="div.product-iWarp" md <- gurl %>%
read_html(encoding="GBK") %>% # 读取gurl的链接,指定编码为gbk
html_nodes("div.product-iWrap") # 筛选出所有包含在...
块的内容
从对象md继续筛选,获卖家名称等数据。
html_attr("data-nick") 是从html_nodes()筛选出的标签中,查找data-nick属性的值。
gsub()是字符串查找替换的函数,pattern是指定用来查找的正则表达式。
html_nodes("p.productTitle>a[title]"),”>"指定的筛选条件的父级标签。
html_text() 只抓取<标签>内容标签>中的内容部分。
# 抓取卖家昵称和ID
sellerNick <- md %>% html_nodes("p.productStatus>span[class]") %>%
html_attr("data-nick")
sellerId <- md %>% html_nodes("p.productStatus>span[data-atp]") %>%
html_attr("data-atp") %>%
gsub(pattern="^.*,",replacement="")
# 抓取宝贝名称等数据
itemTitle <- md %>% html_nodes("p.productTitle>a[title]") %>%
html_attr("title")
itemId <- md %>% html_nodes("p.productStatus>span[class]") %>%
html_attr("data-item")
price <- md %>% html_nodes("em[title]") %>%
html_attr("title") %>%
as.numeric
volume <- md %>% html_nodes("span>em") %>%
html_text
# 最后保存成数据框对象并存盘备用,以及写入csv文件
options(stringsAsFactors = FALSE) # 设置字符串不自动识别为因子
itemData <- data.frame(sellerNick=sellerNick,
sellerId=sellerId,itemTitle=itemTitle,
itemId=itemId,
price=price,
volume=volume)
save(itemData,file="F:/mydata/itemData.rData")
write.csv(itemData,file="F:/mydata/itemData.csv")
补充一个用rvest从赶集网抓取二手房单页面数据的代码
getData <- function(gurl){
# 抓取赶集网二手房源单页的数据
library(rvest)
# 赶集网首页筛选长沙-雨花区-砂子塘的二手房源,获得链接,o1为页数
# gurl <- "http://cs.ganji.com/fang5/yuhuashazitang/o1/"
tmp <- gurl %>% html_session %>%
read_html(encoding="utf-8") %>%
html_nodes("div.f-main-list>div>div")
# 单个房源的puid
puid <- tmp %>% html_attr("id")
# 单个房源的链接
itemURL <-tmp %>% html_attr("href") %>%
gsub(pattern="/fang5",replacement="http://cs.ganji.com/fang5")
# 缩略图链接
smallImg <- tmp %>% html_nodes("dl>dt>div>a>img") %>% html_attr("src")
# 标题
iTitle <- tmp %>% html_nodes("dl>dd>a") %>% html_attr("title")
# 户型
iLayout <- tmp %>% html_nodes("dl>dd[data-huxing]") %>% html_attr("data-huxing")
# 面积
iArea <- tmp %>% html_nodes("dl>dd[data-huxing]") %>%
html_attr("data-area") %>%
gsub(pattern="[^0-9]",replacement="")
# 筛选朝向等数据
iTmp <- tmp %>% html_nodes("dl>dd[data-huxing]>span") %>% html_text
iOrientation <- iTmp[seq(from=5,to=length(iTmp),by=9)] # 提取朝向
iFloor <- iTmp[seq(from=7,to=length(iTmp),by=9)] %>% # 提取楼层
gsub(pattern="\n",replacement="")
iDecoration <- iTmp[seq(from=9,to=length(iTmp),by=9)] # 提取装修
# 提取地址
iAddr <- tmp %>% html_nodes("dl>dd>span.area") %>% html_text %>%
gsub(pattern="\n",replacement=" ") %>%
gsub(pattern=" ",replacement="")
# 提取价格
iPrice <- tmp %>% html_nodes("dl>dd>div.price>span:first-child") %>% html_text
# 提取单价
iTime <- tmp %>% html_nodes("dl>dd>div.time") %>% html_text %>%
gsub(pattern="[^0-9]",replacement="") %>% as.numeric
# 合并数据框
iData <- data.frame(puid=puid,
iLayout=iLayout,
iArea=iArea,
iPrice=iPrice,
iTime=iTime,
iDecoration=iDecoration,
iFloor=iFloor,
iOrientation=iOrientation,
itemURL=itemURL,
smallImg=smallImg,
iTitle=iTitle,
iAddr=iAddr,
stringsAsFactors=FALSE)
# 返回数据框
return(iData)
}
你可能感兴趣的:(r语言,爬虫,runtime)
Anaconda 和 Miniconda:功能详解与选择建议
古月฿
python入门 python conda
Anaconda和Miniconda详细介绍一、Anaconda的详细介绍1.什么是Anaconda?Anaconda是一个开源的包管理和环境管理工具,在数据科学、机器学习以及科学计算领域发挥着关键作用。它以Python和R语言为基础,为用户精心准备了大量预装库和工具,极大地缩短了搭建数据科学环境的时间。对于那些想要快速开展数据分析、模型训练等工作的人员来说,Anaconda就像是一个一站式的“数
Gerapy爬虫管理框架深度解析:企业级分布式爬虫管控平台
Python×CATIA工业智造
爬虫 分布式 python pycharm
引言:爬虫工程化的必然选择随着企业数据采集需求指数级增长,传统单点爬虫管理模式面临三重困境:管理效率瓶颈:手动部署耗时占开发总时长的40%以上系统可靠性低:研究显示超过65%的爬虫故障源于部署或调度错误资源利用率差:平均爬虫服务器CPU利用率不足30%爬虫管理方案对比:┌───────────────┬─────────────┬───────────┬───────────┬──────────
R语言笔记Day1(排序、筛选以及分类汇总))
养猪场小老板
一、排序1、单变量序列排序2、数据表(矩阵)排序二、筛选三、分类汇总一、排序1、单变量序列排序rank、sort和order函数>aa[1]315#rank用来计算序列中每个元素的秩#这里的“秩”可以理解为该元素在序列中由小到大排列的次序#上面例子给出的序列[3,1,5]中,1最小,5最大,3居中#于是1的秩为1,3的秩为2,5的秩为3,(3,1,5)对应的秩的结果就是(2,1,3)>rank(a
在一个存在的包里面编写msg消息文件
CrimsonEmber
ROS笔记 ROS2
前言尽管最佳实践是在专门的接口包中声明接口,但有时在同一个包中完成接口的声明、创建和使用会更为便捷。创建文件创建好msg/AddressBook.msg文件,在你的包的目录下package.xmlrosidl_default_generatorsrosidl_default_runtimerosidl_interface_packagesCMakeList找到生成消息代码的包find_packag
从0开始学习R语言--Day58--竞争风险模型
在用传统生存分析方法的场景中(如Kaplan-Meier和Cox回归),假设所有事件都是独立且互斥的,但在现实中,研究对象可能面临多种互斥的终点事件(如癌症患者可能死于癌症本身,也可能死于其他原因),如果直接去分析,模型会把这种结局时间错误地纳入评估,从而提高了病症的分析。而竞争风险模型可以在考虑其他竞争风险存在的情况下,排除干扰求得某特定事件发生的概率。以下是一个例子:library(cmprs
android开发-bug记录
TUZILE
android开发 android java android studio bug
2022.01.10正式接触android开发刚三四个月,记录一下三个第一次遇到的bug自定义的圆角控件加载图片导致OOMjava.lang.OutOfMemoryError:Failedtoallocatea373980byteallocationwith288904freebytesand282KBuntilOOM//atdalvik.system.VMRuntime.newNonMovabl
解决:RuntimeError: main thread is not in main loop
-米兰的小铁匠
python linux matplotlib bug
很久没更新了,分享一下新近遇到的bug。背景是在做一个demo,用到了多线程,其中一个子线程任务为绘图并保存图片。起初在Windows上运行正常,但将代码迁移至Linux服务器上,运行时发生报错RuntimeError:mainthreadisnotinmainloop。查阅了一下资料,如下:“该错误通常在使用GUI编程库(如Tkinter、PyQt、wxPython等)时出现。这个错误的原因通常
Python爬虫【五十八章】Python数据清洗与分析全攻略:从Pandas到深度学习的异常检测进阶
程序员_CLUB
Python入门到进阶 python 爬虫 pandas
目录背景与需求分析第一章:结构化数据清洗实战(Pandas核心技法)1.1数据去重策略矩阵1.2智能缺失值处理体系第二章:深度学习异常检测进阶2.1自动编码器异常检测(时序数据)2.2图神经网络异常检测(关系型数据)第三章:综合案例实战案例1:金融交易反欺诈系统案例2:工业传感器异常检测第四章:性能优化与工程实践4.1大数据处理加速技巧4.2模型部署方案第五章:方法论总结与展望5.1方法论框架5.
Python【一】Python全方位知识指南
程序员_CLUB
python 开发语言
目录背景:为什么Python成为开发者必备技能?一、Python是什么?二、Python能做什么?六大核心应用场景1.自动化办公2.网络爬虫3.数据分析三、零基础入门Python:环境搭建与学习路径1.环境搭建(Windows/Mac详细步骤)2.基础语法速成(7天掌握)四、实战项目推荐(*****)五、学习建议与避坑指南(新手常见错误)六、总结:**背景:
Python爬虫【三十五章】爬虫高阶:基于Docker集群的动态页面自动化采集系统实战
程序员_CLUB
Python入门到进阶 python 爬虫 docker
目录一、技术演进与行业痛点二、核心技术栈深度解析2.1动态渲染三件套2.2Docker集群架构设计2.3自动化调度系统三、进阶实战案例3.1电商价格监控系统1.技术指标对比2.实现细节3.2新闻聚合平台1.WebSocket监控2.字体反爬破解四、性能优化与运维方案4.1资源消耗对比测试4.2集群运维体系五、总结与未来展望六、Python爬虫相关文章(推荐)一、技术演进与行业痛点在Web3.0时代
Python爬虫【三十二章】爬虫高阶:动态页面处理与Scrapy+Selenium+BeautifulSoup分布式架构深度解析实战
目录引言一、动态页面爬取的技术背景1.1动态页面的核心特征1.2传统爬虫的局限性二、技术选型与架构设计2.1核心组件分析2.2架构设计思路1.分层处理2.数据流三、代码实现与关键技术3.1Selenium与Scrapy的中间件集成3.2BeautifulSoup与ScrapyItem的整合3.3分布式爬取实现3.3.1Scrapy-Redis部署3.3.2多节点启动四、优化与扩展4.1性能优化策略
Python爬虫【三十三章】爬虫高阶:动态页面破解与验证码OCR识别全流程实战
程序员_CLUB
Python入门到进阶 python 爬虫 ocr
目录一、技术背景与行业痛点二、核心技术与实现路径2.1动态页面处理方案对比2.2Selenium深度集成实践2.3OCR验证码破解方案1.预处理阶段:2.识别阶段:3.后处理阶段三、典型应用场景解析3.1电商价格监控系统1.技术架构2.实现效果3.2社交媒体舆情分析1.特殊挑战2.优化方案:四、合规性与风险控制五、总结Python爬虫相关文章(推荐)一、技术背景与行业痛点在Web3.0时代,网站反
Python爬虫【三十四章】爬虫高阶:动态页面处理与Playwright增强控制深度解析
程序员_CLUB
Python入门到进阶 python 爬虫 开发语言
目录一、技术演进背景与行业挑战二、核心技术栈深度解析2.1动态渲染双引擎架构2.2浏览器指纹伪装方案2.3BeautifulSoup集成实践三、进阶应用场景突破3.1电商价格监控系统3.1.1技术架构创新3.1.2实现效果3.2社交媒体舆情分析3.2.1无限滚动模拟3.2.2WebSocket监控3.2.3Canvas指纹防护四、性能优化与合规方案4.1资源消耗对比测试4.2反爬对抗升级方案五、总
Python爬虫【三十一章】爬虫高阶:动态页面处理与Scrapy+Selenium+Celery弹性伸缩架构实战
目录引言一、动态页面爬取的技术挑战1.1动态页面的核心特性1.2传统爬虫的局限性二、Scrapy+Selenium:动态爬虫的核心架构2.1技术选型依据2.2架构设计2.3代码实现示例三、Celery:分布式任务队列的引入3.1为什么需要Celery?3.2Celery架构设计3.3代码实现示例3.4Scrapy与Celery的集成四、优化与扩展4.1性能优化4.2分布式部署4.3反爬对抗五、总结
十年爬虫经验告诉你爬虫被封怎么办
congqian8750
爬虫
十年爬虫经验告诉你爬虫被封怎么办现在很多站长都会有抓取数据的需求,因此网络爬虫在一定程度上越来越火爆,其实爬虫的基本功能很简单,就是分析大量的url的html页面,从而提取新的url,但是在实际操作中通常都会遇到各种各样的问题,比如说抓取数据的过程中需要根据实际需求来筛选url继续爬行;或者说为了能正常爬取,减少别人服务器的压力,你需要控制住爬取的速度和工作量···但是即便再小心,很多时候也会遇到
【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博文章数据可视化分析-文章分类下拉框实现
java1234_小锋
NLP NLLP微博舆情分析 python 自然语言处理 flask
大家好,我是java1234_小锋老师,最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts)视频教程,持续更新中,计划月底更新完,感谢支持。今天讲解微博文章数据可视化分析-文章分类下拉框实现视频在线地址:2026版【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts+爬虫)视频教程(火爆连载更
Scrapy 爬虫 IP 被封问题的解决方案
杨胜增
scrapy 爬虫 tcp/ip
Scrapy爬虫IP被封问题的解决方案在使用Scrapy进行网络爬虫开发时,IP被封是一个常见的问题。当爬虫频繁地向目标网站发送请求时,目标网站可能会检测到异常流量,并将爬虫的IP地址加入黑名单,导致后续请求无法正常访问。本文将详细介绍Scrapy爬虫IP被封问题的原因及解决方案。问题描述在运行Scrapy爬虫时,可能会遇到以下类似的情况:请求返回403Forbidden错误,表示服务器拒绝了请求
Python requests设置代理的3种方法
爱睡觉的圈圈
代理服务 python 网络 开发语言 代理模式
在进行网络爬虫或数据采集时,经常需要使用代理来避免IP被封或突破访问限制。本文介绍Pythonrequests库设置代理的3种常用方法。方法一:基础代理设置最简单的代理设置方式:importrequests#设置代理proxies={'http':'http://proxy_ip:port','https':'https://proxy_ip:port'}#发送请求response=request
代理IP的类型详解:数据中心vs住宅IP
前言做爬虫的时候,代理IP是绕不开的话题。但很多人对代理IP的分类不太了解,经常花了钱却买到不合适的代理,结果还是被封。今天详细聊聊代理IP的分类,特别是数据中心IP和住宅IP的区别,帮你选到最适合的代理。代理IP基础分类按协议分类HTTP代理#只支持HTTP协议proxy={'http':'http://username:
[email protected] :8080'}HTTPS代理#支持HT
如何避免IP被加入黑名单:实用防护指南
爱睡觉的圈圈
代理服务 tcp/ip 网络协议 网络
前言IP被封是爬虫开发者最头疼的问题。很多人以为换个User-Agent就能解决,结果还是被秒封。现代反爬虫系统已经非常智能,不仅看IP访问频率,还会分析浏览器指纹、行为模式、TLS指纹等多个维度。要想真正避免被封,需要从多个角度进行防护。今天分享一套完整的IP保护方案,结合Selenium、指纹浏览器等成熟工具,让你的爬虫更像真实用户。反爬虫检测原理网站如何识别爬虫#现代反爬虫系统的检测维度de
爬虫入门:为什么你的爬虫需要代理IP?
前言作为一名在爬虫领域摸爬滚打多年的程序员,我经常收到新手朋友的疑问:"为什么我的爬虫跑了一会儿就不工作了?"今天,我就来详细讲解为什么爬虫需要代理IP,以及如何正确使用代理IP来提升爬虫的稳定性和效率。一、爬虫面临的挑战1.1反爬虫机制的普及现代网站都配备了各种反爬虫机制,最常见的包括:反爬虫机制IP限制User-Agent检测验证码行为分析请求频率限制1.2IP封禁的痛点让我们看一个典型的爬虫
Python爬虫IP被封的5种解决方案
前言做爬虫的朋友都遇到过这种情况:程序跑得好好的,突然就开始返回403错误,或者直接连接超时。十有八九是IP被网站封了。现在的网站反爬虫越来越严格,稍微频繁一点就会被拉黑。今天分享几个实用的解决方案,都是我在实际项目中用过的。方案一:代理IP池这是最直接的办法,换个马甲继续干活。基本实现importrequestsimportrandomimporttimeclassProxyPool:def__
Python爬虫实战:研究picloud相关技术
ylfhpy
爬虫项目实战 python 爬虫 开发语言 picloud
一、引言1.1研究背景与意义在数字化时代,网络数据已成为企业决策、学术研究和社会服务的重要资源。爬虫技术作为自动化获取网络信息的关键手段,在舆情监测、市场分析、学术研究等领域具有广泛应用。Python以其简洁的语法和丰富的爬虫库(如Requests、BeautifulSoup、Scrapy)成为爬虫开发的首选语言。然而,面对海量数据和高并发需求,本地爬虫系统往往面临性能瓶颈。picloud作为专业
Python爬虫实战:研究flanker相关技术
ylfhpy
爬虫项目实战 python 爬虫 开发语言 flanker
1.引言1.1研究背景与意义在当今信息爆炸的时代,互联网上的数据量呈现出指数级增长的趋势。如何从海量的网页数据中高效地获取有价值的信息,成为了一个重要的研究课题。网络爬虫作为一种自动获取网页内容的技术,能够帮助用户快速、准确地收集所需的信息,因此在信息检索、数据挖掘、舆情分析等领域得到了广泛的应用。Flanker技术是一种基于文本分析的信息提取技术,它能够从非结构化的文本中识别和提取出特定类型的信
Python爬虫实战入门:手把手教你抓取豆瓣电影TOP250
xiaobindeshijie7
python 爬虫 开发语言 其他
文章目录一、环境准备(5分钟搞定)二、第一个爬虫实战(超简单版)2.1基础版代码2.2代码解剖(新人必看)三、突破反爬机制(实战精华)3.1伪装大法3.2请求频率控制3.3代理IP使用四、数据存储(多种姿势)4.1CSV存储4.2MySQL存储五、进阶技巧(高手必备)5.1异步爬虫5.2Selenium动态渲染六、法律与伦理(超级重要!!!)七、下一步学习路线一、环境准备(5分钟搞定)工欲善其事必
BeautifulSoup库深度解析:Python高效解析网页数据的秘籍
在Python爬虫开发领域,获取网页内容后,如何高效解析并提取所需数据是关键一环。BeautifulSoup库凭借其简洁易用、功能强大的特点,成为众多开发者解析网页数据的首选工具。本文将深入剖析BeautifulSoup库,通过丰富的实例,帮助你掌握其核心功能与使用技巧,实现网页数据的精准提取。一、认识BeautifulSoup库BeautifulSoup是Python的一个第三方库,主要用于解析
Python BeautifulSoup 解析网页按钮元素
PythonAI编程架构实战家
Python人工智能与大数据 Python编程之道 python beautifulsoup 开发语言 ai
PythonBeautifulSoup解析网页按钮元素:从基础原理到工程实践的深度解析关键词BeautifulSoup、HTML解析、按钮元素定位、DOM树遍历、CSS选择器、网络爬虫、前端自动化摘要本文系统解析使用PythonBeautifulSoup库定位和提取网页按钮元素的全流程技术方案。从HTML文档的底层结构出发,结合BeautifulSoup的核心解析机制,覆盖从基础概念到高级工程实践
Python网络爬虫技术深度解析:从入门到高级实战
Python爬虫项目
2025年爬虫实战项目 python 爬虫 开发语言 easyui scrapy
1.爬虫技术概述网络爬虫(WebCrawler)是一种自动化程序,通过模拟人类浏览行为从互联网上抓取、解析和存储数据。根据应用场景可分为:通用爬虫:如搜索引擎的蜘蛛程序聚焦爬虫:针对特定领域的数据采集增量式爬虫:只抓取更新内容深层网络爬虫:处理需要交互的动态内容2.2024年Python爬虫技术栈技术分类推荐工具适用场景基础请求库requests,httpx静态页面请求解析库BeautifulSo
XPath
class心平气和
服务器 前端 运维
一、XPath基础概念XPath(XMLPathLanguage)是一种用于在XML或HTML文档中定位节点的语言,广泛应用于网页爬虫、数据提取和文档处理。以下将从基础概念到高级技巧全面解析XPath。XPath是一种路径表达式语言,用于在XML/HTML文档中导航和选择节点。二、XPath路径表达式基础1.绝对路径与相对路径绝对路径:从根节点开始,用/分隔,例:/html/body/div#从H
MyBatis与MyBatis-Plus批量插入实战指南
代码小侦探
mybatis
在实际项目中,批量插入数据是一个常见且重要的需求。本文将详细总结MyBatis和MyBatis-Plus常用的几种批量插入方式,并通过实际代码示例和运行结果,帮助大家更好地理解和应用。一、准备工作导入pom.xml依赖mysqlmysql-connector-javaruntimeorg.mybatis.spring.bootmybatis-spring-boot-starter2.2.2com.
scala的option和some
矮蛋蛋
编程 scala
原文地址:
http://blog.sina.com.cn/s/blog_68af3f090100qkt8.html
对于学习 Scala 的 Java™ 开发人员来说,对象是一个比较自然、简单的入口点。在 本系列 前几期文章中,我介绍了 Scala 中一些面向对象的编程方法,这些方法实际上与 Java 编程的区别不是很大。我还向您展示了 Scala 如何重新应用传统的面向对象概念,找到其缺点
NullPointerException
Cb123456
android BaseAdapter
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getImportantForAccessibility()' on a null object reference
出现以上异常.然后就在baidu上
PHP使用文件和目录
天子之骄
php文件和目录 读取和写入 php验证文件 php锁定文件
PHP使用文件和目录
1.使用include()包含文件
(1):使用include()从一个被包含文档返回一个值
(2):在控制结构中使用include()
include_once()函数需要一个包含文件的路径,此外,第一次调用它的情况和include()一样,如果在脚本执行中再次对同一个文件调用,那么这个文件不会再次包含。
在php.ini文件中设置
SQL SELECT DISTINCT 语句
何必如此
sql
SELECT DISTINCT 语句用于返回唯一不同的值。
SQL SELECT DISTINCT 语句
在表中,一个列可能会包含多个重复值,有时您也许希望仅仅列出不同(distinct)的值。
DISTINCT 关键词用于返回唯一不同的值。
SQL SELECT DISTINCT 语法
SELECT DISTINCT column_name,column_name
F
java冒泡排序
3213213333332132
java 冒泡排序
package com.algorithm;
/**
* @Description 冒泡
* @author FuJianyong
* 2015-1-22上午09:58:39
*/
public class MaoPao {
public static void main(String[] args) {
int[] mao = {17,50,26,18,9,10
struts2.18 +json,struts2-json-plugin-2.1.8.1.jar配置及问题!
7454103
DAO spring Ajax json qq
struts2.18 出来有段时间了! (貌似是 稳定版)
闲时研究下下! 貌似 sruts2 搭配 json 做 ajax 很吃香!
实践了下下! 不当之处请绕过! 呵呵
网上一大堆 struts2+json 不过大多的json 插件 都是 jsonplugin.34.jar
strut
struts2 数据标签说明
darkranger
jsp bean struts servlet Scheme
数据标签主要用于提供各种数据访问相关的功能,包括显示一个Action里的属性,以及生成国际化输出等功能
数据标签主要包括:
action :该标签用于在JSP页面中直接调用一个Action,通过指定executeResult参数,还可将该Action的处理结果包含到本页面来。
bean :该标签用于创建一个javabean实例。如果指定了id属性,则可以将创建的javabean实例放入Sta
链表.简单的链表节点构建
aijuans
编程技巧
/*编程环境WIN-TC*/ #include "stdio.h" #include "conio.h"
#define NODE(name, key_word, help) \ Node name[1]={{NULL, NULL, NULL, key_word, help}}
typedef struct node { &nbs
tomcat下jndi的三种配置方式
avords
tomcat
jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API。命名服务将名称和对象联系起来,使得我们可以用名称
访问对象。目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性。
tomcat配置
关于敏捷的一些想法
houxinyou
敏捷
从网上看到这样一句话:“敏捷开发的最重要目标就是:满足用户多变的需求,说白了就是最大程度的让客户满意。”
感觉表达的不太清楚。
感觉容易被人误解的地方主要在“用户多变的需求”上。
第一种多变,实际上就是没有从根本上了解了用户的需求。用户的需求实际是稳定的,只是比较多,也比较混乱,用户一般只能了解自己的那一小部分,所以没有用户能清楚的表达出整体需求。而由于各种条件的,用户表达自己那一部分时也有
富养还是穷养,决定孩子的一生
bijian1013
教育 人生
是什么决定孩子未来物质能否丰盛?为什么说寒门很难出贵子,三代才能出贵族?真的是父母必须有钱,才能大概率保证孩子未来富有吗?-----作者:@李雪爱与自由
事实并非由物质决定,而是由心灵决定。一朋友富有而且修养气质很好,兄弟姐妹也都如此。她的童年时代,物质上大家都很贫乏,但妈妈总是保持生活中的美感,时不时给孩子们带回一些美好小玩意,从来不对孩子传递生活艰辛、金钱来之不易、要懂得珍惜
oracle 日期时间格式转化
征客丶
oracle
oracle 系统时间有 SYSDATE 与 SYSTIMESTAMP;
SYSDATE:不支持毫秒,取的是系统时间;
SYSTIMESTAMP:支持毫秒,日期,时间是给时区转换的,秒和毫秒是取的系统的。
日期转字符窜:
一、不取毫秒:
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS')
简要说明,
YYYY 年
MM 月
【Scala六】分析Spark源代码总结的Scala语法四
bit1129
scala
1. apply语法
FileShuffleBlockManager中定义的类ShuffleFileGroup,定义:
private class ShuffleFileGroup(val shuffleId: Int, val fileId: Int, val files: Array[File]) {
...
def apply(bucketId
Erlang中有意思的bug
bookjovi
erlang
代码中常有一些很搞笑的bug,如下面的一行代码被调用两次(Erlang beam)
commit f667e4a47b07b07ed035073b94d699ff5fe0ba9b
Author: Jovi Zhang <
[email protected] >
Date: Fri Dec 2 16:19:22 2011 +0100
erts:
移位打印10进制数转16进制-2008-08-18
ljy325
java 基础
/**
* Description 移位打印10进制的16进制形式
* Creation Date 15-08-2008 9:00
* @author 卢俊宇
* @version 1.0
*
*/
public class PrintHex {
// 备选字符
static final char di
读《研磨设计模式》-代码笔记-组合模式
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
import java.util.ArrayList;
import java.util.List;
abstract class Component {
public abstract void printStruct(Str
利用cmd命令将.class文件打包成jar
chenyu19891124
cmd jar
cmd命令打jar是如下实现:
在运行里输入cmd,利用cmd命令进入到本地的工作盘符。(如我的是D盘下的文件有此路径 D:\workspace\prpall\WEB-INF\classes)
现在是想把D:\workspace\prpall\WEB-INF\classes路径下所有的文件打包成prpall.jar。然后继续如下操作:
cd D: 回车
cd workspace/prpal
[原创]JWFD v0.96 工作流系统二次开发包 for Eclipse 简要说明
comsci
eclipse 设计模式 算法 工作 swing
JWFD v0.96 工作流系统二次开发包 for Eclipse 简要说明
&nb
SecureCRT右键粘贴的设置
daizj
secureCRT 右键 粘贴
一般都习惯鼠标右键自动粘贴的功能,对于SecureCRT6.7.5 ,这个功能也已经是默认配置了。
老版本的SecureCRT其实也有这个功能,只是不是默认设置,很多人不知道罢了。
菜单:
Options->Global Options ...->Terminal
右边有个Mouse的选项块。
Copy on Select
Paste on Right/Middle
Linux 软链接和硬链接
dongwei_6688
linux
1.Linux链接概念Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。默认情况下,ln命令产生硬链接。
【硬连接】硬连接指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号(Inode Index)。在Linux中,多个文件名指向同一索引节点是存在的。一般这种连
DIV底部自适应
dcj3sjt126com
JavaScript
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml&q
Centos6.5使用yum安装mysql——快速上手必备
dcj3sjt126com
mysql
第1步、yum安装mysql
[root@stonex ~]# yum -y install mysql-server
安装结果:
Installed:
mysql-server.x86_64 0:5.1.73-3.el6_5 &nb
如何调试JDK源码
frank1234
jdk
相信各位小伙伴们跟我一样,想通过JDK源码来学习Java,比如collections包,java.util.concurrent包。
可惜的是sun提供的jdk并不能查看运行中的局部变量,需要重新编译一下rt.jar。
下面是编译jdk的具体步骤:
1.把C:\java\jdk1.6.0_26\sr
Maximal Rectangle
hcx2013
max
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.
public class Solution {
public int maximalRectangle(char[][] matrix)
Spring MVC测试框架详解——服务端测试
jinnianshilongnian
spring mvc test
随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的。从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用spring-test-mvc项目(合并到spring3.2中了)。
Spring MVC测试框架提供了对服务器端和客户端(基于RestTemplate的客户端)提供了支持。
&nbs
Linux64位操作系统(CentOS6.6)上如何编译hadoop2.4.0
liyong0802
hadoop
一、准备编译软件
1.在官网下载jdk1.7、maven3.2.1、ant1.9.4,解压设置好环境变量就可以用。
环境变量设置如下:
(1)执行vim /etc/profile
(2)在文件尾部加入:
export JAVA_HOME=/home/spark/jdk1.7
export MAVEN_HOME=/ho
StatusBar 字体白色
pangyulei
status
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
/*you'll also need to set UIViewControllerBasedStatusBarAppearance to NO in the plist file if you use this method
如何分析Java虚拟机死锁
sesame
java thread oracle 虚拟机 jdbc
英文资料:
Thread Dump and Concurrency Locks
Thread dumps are very useful for diagnosing synchronization related problems such as deadlocks on object monitors. Ctrl-\ on Solaris/Linux or Ctrl-B
位运算简介及实用技巧(一):基础篇
tw_wangzhengquan
位运算
http://www.matrix67.com/blog/archives/263
去年年底写的关于位运算的日志是这个Blog里少数大受欢迎的文章之一,很多人都希望我能不断完善那篇文章。后来我看到了不少其它的资料,学习到了更多关于位运算的知识,有了重新整理位运算技巧的想法。从今天起我就开始写这一系列位运算讲解文章,与其说是原来那篇文章的follow-up,不如说是一个r
jsearch的索引文件结构
yangshangchuan
搜索引擎 jsearch 全文检索 信息检索 word分词
jsearch是一个高性能的全文检索工具包,基于倒排索引,基于java8,类似于lucene,但更轻量级。
jsearch的索引文件结构定义如下:
1、一个词的索引由=分割的三部分组成: 第一部分是词 第二部分是这个词在多少