In [2]:
# 载入rpy2.ipython
# rpy2提供了Python和R之间的交互环境
%load_ext rpy2.ipython
rvest包里面主要有以下几个函数:
read_html(x, ..., encoding = "", as_html = FALSE)
: 既可以从网络中获取html文档,也可以从本地中载入html文档;html_nodes(x, css, xpath)
: 利用css和xpath选择器从html文档中提取出节点信息;html_text(x)
: 提取所有满足条件的文本信息;html_attrs(x)
: 提取所有满足条件的属性信息;html_table(x, header = NA, trim = TRUE, fill = FALSE, dec = ".")
: 提取表格信息;html_session(), jump_to(), follow_link(), back(), forward()
: 这些都是用于模拟浏览网站
In [3]:
%%R
library(rvest)
# vignette("selectorgadget")
lego_movie <- read_html("http://www.imdb.com/title/tt1490017/")
In [4]:
%%R
lego_movie
In [8]:
%%R
rating <- lego_movie %>%
html_nodes("strong span")
rating
In [9]:
%%R
cast <- lego_movie %>%
html_nodes("#titleCast .itemprop span") %>%
html_text()
cast
In [10]:
%%R
poster <- lego_movie %>%
html_nodes(xpath="//div[@class='poster']/a/img") %>%
html_attr("src")
poster
首先,urllib*中包含了urllib, urllib2和urllib3等几个模块。其中urllib3是第三方扩展模块,所以在这里我们只讨论前两个Python自带模块。那么这两个模块之间到底有何区别呢?
官方文档对urllib和urllib2分别是这样描述的:“通过url打开任意资源”和“打开url的拓展库”。urllib2主要用于处理一些更复杂的操作,比如操作相关的一些认证、重定向和cookie等等。
urllib模块中主要有以下几个方法:
In [11]:
import urllib
f = urllib.urlopen('http://www.baidu.com')
firstLine = f.readline()
firstLine
Out[11]:
In [12]:
file = urllib.urlretrieve('http://www.baidu.com/', filename='baidu.html')
file
Out[12]:
In [13]:
urllib.quote('经济学院')
Out[13]:
In [14]:
print urllib.unquote('%E7%BB%8F%E6%B5%8E%E5%AD%A6%E9%99%A2')
In [16]:
Data = urllib.urlencode({'UserName':'fibears','PassWd':123456})
Data
Out[16]:
In [11]:
# GET 方法
# GET方式是直接以链接形式访问,链接中包含了所有的参数。
response = urllib.urlopen("http://event.wisesoe.com/Logon.aspx" + '?' + Data)
# response.read()
In [17]:
"http://event.wisesoe.com/Logon.aspx" + '?' + Data
Out[17]:
In [13]:
# POST 方法
# POST将参数以变量的形式传递给处理器,所以不会在网址上显示所有的参数。
response = urllib.urlopen("http://event.wisesoe.com/Logon.aspx",Data)
# response.read()
urllib2模块中主要有以下几个方法:
In [5]:
import urllib2
response1 = urllib2.urlopen("http://www.baidu.com")
# print response1.read()
In [6]:
request = urllib2.Request('http://www.baidu.com')
response2 = urllib2.urlopen(request)
# print response2.read()
In [16]:
# GET 方法
Data = urllib.urlencode({'UserName':'fibears','PassWd':123456})
GetUrl = "http://event.wisesoe.com/Logon.aspx" + '?' + Data
print GetUrl
request = urllib2.Request(GetUrl)
response = urllib2.urlopen(request)
In [17]:
# POST 方法
Data = urllib.urlencode({'UserName':'fibears','PassWd':123456})
Url = "http://event.wisesoe.com/Logon.aspx"
request = urllib2.Request(Url, Data)
response = urllib2.urlopen(request)
有些网站不会同意程序直接用上面的方式进行访问,站点根本不会响应我们所发出的简单请求,所以为了完全模拟浏览器的工作,我们需要设置一些Headers的属性。以下是几个常用的 Headers 属性:
In [18]:
Data = urllib.urlencode({'UserName':'fibears','PassWd':123456})
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Firefox/45.0'
headers = {'User-Agent' : user_agent,
'Referer': 'http://event.wisesoe.com/Authenticate.aspx?returnUrl=/LectureOrder.aspx'}
Url = "http://event.wisesoe.com/LectureOrder.aspx"
request = urllib2.Request(Url, Data, headers)
response = urllib2.urlopen(request)
有的网站会检测某一段时间内某个 IP 访问网页的次数,如果访问过于频数,它会禁止该 IP 对网页的访问。这种情况下,我们通常有两种处理办法,一是设置延迟机制,降低爬虫程序发出请求的频率;二是设置代理服务器,每隔一段时间更换一个代理,这样就不会被躲过网站的检测机制。我们可以利用urllib2.ProxyHandler方法来设置代理:
In [19]:
# 设置代理
import urllib2
proxy_handler = urllib2.ProxyHandler({"http" : 'http://some-proxy.com:8080'})
opener = urllib2.build_opener(proxy_handler)
# urllib2.install_opener(opener)
Cookie指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据。
有些网站需要登录后才能访问某个页面,在登录之前,我们无法获取网页的内容。这种情况下我们可以利用urllib2库保存登录网页的Cookie,然后再利用该Cookie来抓取其他页面。
步骤:
In [8]:
import urllib
import urllib2
import cookielib
# 声明cookie文件的存储路径
CookieFile = "cookie.txt"
# 构建一个MozillaCookieJar对象来保存cookie文件
cookie = cookielib.MozillaCookieJar(CookieFile)
# urlopen()方法就是一个特殊的opener
# 构建一个带有Cookie的处理器opener
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
# 利用处理器opener发出HTTP请求
Data = urllib.urlencode({'UserName':'fibears','PassWd':123456})
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Firefox/45.0'
headers = {'User-Agent' : user_agent,
'Referer': 'http://event.wisesoe.com/Authenticate.aspx?returnUrl=/LectureOrder.aspx'}
LectureUrl = "http://event.wisesoe.com/LectureOrder.aspx"
request = urllib2.Request(LectureUrl, Data, headers)
response = opener.open(request)
print cookie
# 将Cookie保存到本地
# ignore_discard: 即使浏览网页过程中cookie被丢弃也将其保存下来
# ignore_expires: 对于文件中已经存在的cookie,将其覆盖并写入新的信息
cookie.save(ignore_discard=True, ignore_expires=True)
# 读取Cookie并构建用于访问网页的opener
cookie = cookielib.MozillaCookieJar()
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
# 发出HTTP请求,并得到返回的响应文件
request = urllib2.Request(LectureUrl, Data, headers)
response = opener.open(request)
# print response.read()
接下来我以结构比较简单的豆瓣网站为例,分别介绍如何利用rvest和urllib2从网上爬取数据。
In [21]:
%%R
library(RCurl)
library(rvest)
library(stringr)
library(plyr)
library(dplyr)
In [23]:
%%R
# 爬取豆瓣电影TOP250的数据
# 获取豆瓣电影首页URL
DoubanUrl <- 'http://movie.douban.com/top250'
# 从首页中获取所有页面的URL
PageUrlList <- read_html(DoubanUrl) %>%
html_nodes(xpath = "//div[@class='paginator']/a") %>%
html_attr("href") %>%
str_c(DoubanUrl, ., sep="") %>% c(DoubanUrl,.)
PageUrlList
In [25]:
%%R
# 从每个PageUrl中提取出每部电影的链接
MovieUrl <- NULL
for (url in PageUrlList) {
item = read_html(url) %>%
html_nodes(xpath="//div[@class='hd']/a") %>%
html_attrs("href")
MovieUrl = c(MovieUrl, item)
}
head(MovieUrl,5)
In [24]:
%%R
# 从每个MovieUrl中提取出最终的数据
## 定义函数Getdata,用于获取数据并输出dataframe格式
GetImdbScore <- function(url){
ImdbScore = read_html(url) %>%
html_nodes(xpath = "//span[@itemprop='ratingValue']/text()") %>%
html_text()
return(ImdbScore)
}
Getdata <- function(url){
Movie = url
if(url.exists(url)){
MovieHTML = read_html(url, encoding = 'UTF-8')
Rank = html_nodes(MovieHTML, xpath = "//span[@class='top250-no']/text()") %>% html_text()
MovieName = html_nodes(MovieHTML, xpath = "//span[@property='v:itemreviewed']/text()") %>% html_text()
Director = html_nodes(MovieHTML, xpath = "//a[@rel='v:directedBy']/text()") %>%
html_text() %>% paste(collapse = ";")
Type = html_nodes(MovieHTML, xpath = "//span[@property='v:genre']/text()") %>%
html_text() %>% paste(collapse = ";")
Score = html_nodes(MovieHTML, xpath = "//strong[@property='v:average']/text()") %>% html_text()
ImdbUrl = html_nodes(MovieHTML, xpath = "//a[contains(@href,'imdb')]/@href") %>% html_text()
ImdbScore = GetImdbScore(ImdbUrl)
Description = html_nodes(MovieHTML, xpath = "//span[@property='v:summary']/text()") %>%
html_text() %>% str_replace("\n[\\s]+", "") %>% paste(collapse = ";")
data.frame(Rank, Movie, MovieName, Director, Type, Score, ImdbScore, Description)
}
}
In [25]:
%%R
## 抓取数据
Douban250 <- data.frame()
for (i in 1:2) {
Douban250 = rbind(Douban250, Getdata(MovieUrl[i]))
print(paste("Movie",i,sep = "-"))
Sys.sleep(round(runif(1,1,3)))
}
Douban250
# for (i in 1:length(MovieUrl)) {
# Douban250 = rbind(Douban250, Getdata(MovieUrl[i]))
# print(paste("Movie",i,sep = "-"))
# Sys.sleep(round(runif(1,1,3)))
# }
In [9]:
%%R
# 豆瓣API
url <- "https://api.douban.com/v2/movie/1292052"
library(rvest)
result <- read_html(url)
result <- html_nodes(result, "p") %>% html_text()
In [39]:
%%R
class(result)
In [28]:
%%R
# 这是json(javascript online notation)格式的文件,可以利用rjson中的函数fromJSON将其转化为结构化的数据。
Movie = rjson::fromJSON(result)
In [29]:
%%R
Movie
In [ ]: