内容简介:数据处理的数据集并非立即可得,有时我们需要自己收集�数据,对很多研究领域,网页内容是一个重要的数据源。
数据处理的数据集并非立即可得,有时我们需要自己收集�数据,对很多研究领域,网页内容是一个重要的数据源。
查阅网页内容
下面是一个简单的网页,几乎所有的网页都可以查看源代码(一般是右键——点击查看源代码)。
<!DOCTYPE html> <html> <head> <title>Simple page</title> </head> <body> <h1>Heading 1</h1> <p>This is a paragraph.</p> </body> </html>
网页源码其实是HTML(Hyper Text Markup Language)文件。HTML是互联网使用最广泛的语言,它描述了网页的布局排版和内容,浏览器则根据Web标准将代码渲染到网页上。
尽管上面的网页代码很简单,但实际上认真点就会发现HTML是一些标签的嵌套结构,这些标签包括: <html>
、 <title>
、 <body>
、 <h1>
和 <p>
,现代浏览器根据HTML的第一行决定使用哪种标准进行网页渲染。上面例子使用的是HTML 5。
网页的这些标签并不是随意命名的,也不能任意包含其他标签,每个标签对浏览器都有特殊含义,且只允许包含一部分特定标签或不允许包含任何标签。
标签 <html>
是所有HTML的根元素。HTML通常也包括 <head>
和 <body>
。其中 <head>
通常包含 <title>
,展示在标题栏,包含浏览标签和网页元数据。而 <body>
则在网页内容和排版方面起主要作用。
在 <body>
标签中,标签可以更自由地嵌套,最简单的一个网页可以只包含一级标题( <h1>
)和一个段落( <p>
)。
关于表格:
<table> <tr> <th> <td>
一些其他标签:
<div> <ul> <li> <span>
HTML有一个属性,称为style,用于定义这些元素的样式外观。
HTML使用CSS可以避免冗长的样式定义。
每个CSS元素都包含一个CSS选择器用来匹配HTML元素和样式以便渲染应用。CSS选择器不仅用于应用样式,也常用于提取网页内容,以便我们感兴趣的HTML元素可以被正确匹配,这正是网络爬虫的底层技术。
对于网络爬虫,使用下面例子展示最常见的CSS选择器
语法 | 匹配 |
---|---|
*
|
All elements |
h1,h2,h3
|
<h1>,<h2>,<h3>
|
#table
|
<* id="table">
|
.product-list
|
<* class="product-list">
|
div#container
|
<div id="container">
|
div a
|
<div><a>and<div><p><a>
|
div >a
|
<div><a>but not<div><p><a>
|
div >a.new
|
<div><a class="new">
|
ul > li:first-child
|
First <li> in <ul>
|
ul > li:last-child
|
Last <li> in <ul>
|
ul > li:nth-child(3)
|
3rd <li> in <ul>
|
p + *
|
Next element of <p>
|
img[title]
|
<img> with title attribute
|
table[border=l]
|
<table border="l">
|
使用CSS选择器从网页中提取数据
R里面爬虫最简单易用的扩展包是 rvest
,安装:
install.packages("rvest")
下面我们读取一个简单表格HTML数据并提取表格:
library(rvest) #> 载入需要的程辑包:xml2 single_table_page = read_html("../../R/learningR_data/single-table.html") single_table_page #> {xml_document} #> <html> #> [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset= ... #> [2] <body>\n <p>The following is a table</p>\n <table id="table1" bord ...
single_table_page
是HTML解析文档,是HTML节点的嵌套数据结构。
使用 rvest
函数从网页上爬取信息的典型过程是这样的。首先,定位需要从中提取数据的HTML节点。然后使用CSS选择器或者XPath表达式筛选HTML节点,从而选择需要的节点,剔除不需要的节点。最后,对已解析的网页使用合适的选择器,用 html_nodes()
提取节点子集,用 html_attrs()
提取属性,用 html_text()
提取文本。
rvest
包提供了一些简单函数可直接用于提取数据并返回一个数据框,例如提取网页中的 <table>
元素,直接使用 html_table()
:
html_table(single_table_page) #> [[1]] #> Name Age #> 1 Jenny 18 #> 2 James 19
为提取第一个元素,我们先选择第一个节点,然后再提取表格:
html_table(html_node(single_table_page, "table")) #> Name Age #> 1 Jenny 18 #> 2 James 19
连续的操作可以使用管道:
single_table_page %>% html_node("table") %>% html_table() #> Name Age #> 1 Jenny 18 #> 2 James 19
现在我们读取一个产品信息网页,然后用 html_nodes()
匹配 <span class="name">
节点:
products_page = read_html("../../R/learningR_data/products.html") products_page %>% html_nodes(".product-list li .name") #> {xml_nodeset (3)} #> [1] <span class="name">Product-A</span> #> [2] <span class="name">Product-B</span> #> [3] <span class="name">Product-C</span>
这里我们选择的是product-list类的 <li>
标签下name类的节点,因此使用 .product-list li .name
,如果对符号不熟悉,需要详细记忆CSS表。
之后提取内容:
products_page %>% html_nodes(".product-list li .name") %>% html_text() #> [1] "Product-A" "Product-B" "Product-C"
类似的可以提取产品价格:
products_page %>% html_nodes(".product-list li .price") %>% html_text() #> [1] "$199.95" "$129.95" "$99.95"
使用XPath选择器
一般来说,CSS选择器足够满足绝大多数HTML节点匹配的需要。但需要根据某些特殊条件选择节点时,需要更强大的技术。
请看下面新的产品信息网页的源代码:
<!DOCTYPE html> <html> <head> <title>New Products</title> <style> p { margin: 2px; } .product-list { width: 80%; } .product-list ul { padding-left: 8px; } .product-list ul li { padding-left: 2px; list-style: none; } .product-list > ul > li { margin-top: 16px; list-style: none; } .product-list .name { font-weight: bold; font-size: 1.25em; } .product-list .price { color: green; } .product-list .info { background-color: #efefef; border-radius: 4px; } .info-key { font-weight: bold; } .info-value { } .unit { padding-left: 4px; color: #818181; } .bordered { border: 1px gray dashed; border-radius: 4px; } </style> </head> <body> <h1>New Products</h1> <p>The following is a list of products</p> <div id="list" class="product-list"> <ul> <li> <span class="name">Product-A</span> <span class="price">$199.95</span> <div class="info bordered"> <p>Description for Product-A</p> <ul> <li><span class="info-key">Quality</span> <span class="info-value">Good</span></li> <li><span class="info-key">Duration</span> <span class="info-value">5</span><span class="unit">years</span></li> </ul> </div> </li> <li class="selected"> <span class="name">Product-B</span> <span class="price">$129.95</span> <div class="info"> <p>Description for Product-B</p> <ul> <li><span class="info-key">Quality</span> <span class="info-value">Medium</span></li> <li><span class="info-key">Duration</span> <span class="info-value">2</span><span class="unit">years</span></li> </ul> </div> </li> <li> <span class="name">Product-C</span> <span class="price">$99.95</span> <div class="info"> <p>Description for Product-C</p> <ul> <li><span class="info-key">Quality</span> <span class="info-value">Good</span></li> <li><span class="info-key">Duration</span> <span class="info-value">4</span><span class="unit">years</span></li> </ul> </div> </li> </ul> </div> <p>All products are available for sale!</p> </body> </html>
我们先读入网页:
page = read_html("../../R/learningR_data/new-products.html")
在继续之前,我们需要了解下XML,编写良好且组织规范的HTML文档可以被看做XML文档的一个特例,与HTML不同,XML允许任意的标签和属性。下面是一个简单示例:
<?xml version = "1.0"?> <root> <product id = "1"> <name>Product-A</name> <price>$199.95</price> </product> <product id = "2"> <name>Product-B</name> <price>$129.95</price> </product> </root>
XPath专门用于提取XML文档中的数据, html_nodes()
支持XPath表达式,可以通过参数 xpath=
实现。
CSS选择器会匹配所有子层级的节点,而XPath表达式中,标签 //
和 /
匹配不同的节点,即 //
标签引用所有子层级的节点,而 /
标签只引用第1个子层级的 <tag>
节点。
下面是一些用法:
-
选择所有
<p>
节点
page %>% html_nodes(xpath = "//p") #> {xml_nodeset (5)} #> [1] <p>The following is a list of products</p> #> [2] <p>Description for Product-A</p> #> [3] <p>Description for Product-B</p> #> [4] <p>Description for Product-C</p> #> [5] <p>All products are available for sale!</p>
选择所有具有class属性的 <li>
节点:
page %>% html_nodes(xpath = "//li[@class]") #> {xml_nodeset (1)} #> [1] <li class="selected">\n <span class="name">Product-B</span>\n ...
选择 <div id = "list"><ul>
节点所有 <li>
子节点:
page %>% html_nodes(xpath = "//div[@id = 'list']/ul/li") #> {xml_nodeset (3)} #> [1] <li>\n <span class="name">Product-A</span>\n <span cla ... #> [2] <li class="selected">\n <span class="name">Product-B</span>\n ... #> [3] <li>\n <span class="name">Product-C</span>\n <span cla ...
选择所有嵌套于 <div id = "list">
中 <li>
标签下的 <span class = "name">
子节点:
page %>% html_nodes(xpath = "//div[@id = 'list']//li/span[@class='name']") #> {xml_nodeset (3)} #> [1] <span class="name">Product-A</span> #> [2] <span class="name">Product-B</span> #> [3] <span class="name">Product-C</span>
选择嵌套于 <li class = "selected">中<span class = "name">
子节点。
page %>% html_nodes(xpath = "//li[@class='selected']/span[@class = 'name']") #> {xml_nodeset (1)} #> [1] <span class="name">Product-B</span>
下面例子就不能用等效CSS来实现了:
-
选择所有包含
<p>
子节点的<div>
节点:
page %>% html_nodes(xpath = "//div[p]") #> {xml_nodeset (3)} #> [1] <div class="info bordered">\n <p>Description for Product-A< ... #> [2] <div class="info">\n <p>Description for Product-B</p>\n ... #> [3] <div class="info">\n <p>Description for Product-C</p>\n ...
-
选择所有的
<span class = "info-value">Good</span>
page %>% html_nodes(xpath = "//span[@class ='info-value' and text() = 'Good']") #> {xml_nodeset (2)} #> [1] <span class="info-value">Good</span> #> [2] <span class="info-value">Good</span>
XPath非常灵活,在匹配节点方面是强大的工具。
更多匹配内容可以阅读W3School。
以上所述就是小编给大家介绍的《R-网页爬虫:初识》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Trading and Exchanges
Larry Harris / Oxford University Press, USA / 2002-10-24 / USD 95.00
This book is about trading, the people who trade securities and contracts, the marketplaces where they trade, and the rules that govern it. Readers will learn about investors, brokers, dealers, arbit......一起来看看 《Trading and Exchanges》 这本书的介绍吧!