爬取豆瓣热映电影

1. 什么是爬虫

爬虫的概念其实很简单,指的是抓取网页内容。其实我们在浏览网页的时候,也可以说是在抓取网页内容,而爬虫可以说是程序在抓取网页内容。为什么需要爬虫呢?想象一下,当只有一个网页而内容不多的时候,我们只需要简单地浏览一下就可以得到我们所需要的信息了。但是当网页非常多时,恐怕人工是不能胜任的,这时通过写一个程序访问网页,提取我们所需要的信息,是一件很有意思的事。

2. 用python进行网络爬虫

用python进行网络爬虫用到的基础库(还有Scrapy这样的高级库)主要有:

2.1 获取网页源代码

爬虫的第一步便是访问网页,获取网页内容,也就是获取网页的源代码。假设我们现在访问的网页是豆瓣主页,在浏览器上,我们可以看到布局清晰的页面,有豆瓣读书,豆瓣电影等模块。我们在网页上点击鼠标右键,选择菜单中的显示网页源代码(或查看源文件等),可以看到网页的html代码,如下:


豆瓣

这些html代码经过浏览器渲染后,就得到了我们平时所见的网页。

下面,我们通过一个简单的程序来获取网页的源代码:

1
2
3
4
import urllib2
response = urllib2.urlopen('http://www.douban.com/')
html = response.read()
print html

将其保存为example.py,运行程序python example.py > result.txt,用文本文件打开result.txt,我们可以看到网页的源代码,与刚刚右键点击显示的网页源代码是一样的。需要注意的是,上面是简化了的代码,一般情况下,我们可能还需要处理身份请求动态传递参数代理设置URLError异常等。

2.2 提取信息

当得到网页的源代码后,我们接下来就要对这些代码进行解析了,提取我们想要的内容。我们可以看到网页源代码很繁杂,几乎不知从何入手。幸运的是,我们可以通过一些库来完成我们的提取工作,比如BeautifulSouplxmlre等,一些简单的提取可以采用正则表达式来完成,但一般情况下我们会采用BeautifulSoup,lxml等专门的网页解析库。

现在,我们把网页定位到豆瓣电影



根据前面介绍的方法,我们可以获得网页源代码,现在我们要提取出正在热映的电影标题和评分。我们通过查找,可以发现电影信息出现在如下的标记中:



因此,我们可以构造如下的正则表达式,提取电影标题和评分:

1
pattern = re.compile('data-title="(.*?)".*data-rate="(.*?)"')

在python中使用正则表达式可参考此教程

3. 爬取豆瓣热映电影

我们对上述的代码进行完善,加入身份请求,异常处理等,并写成一个类,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# -*- coding: utf-8 -*-
import urllib2
import re
# 豆瓣类
class DouBan:
# 初始化方法,定义一些变量
def __init__(self):
self.url = 'http://movie.douban.com/'
# 伪装成浏览器,防止403错误
self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
# 初始化headers
self.headers = {'User-Agent': self.user_agent}
# 获取页面html代码
def getPageSource(self):
try:
# 构建请求的request
request = urllib2.Request(self.url, headers = self.headers)
# 利用urlopen获取页面代码
response = urllib2.urlopen(request)
pageSource = response.read()
# print pageSource
return pageSource
except urllib2.URLError, e:
if hasattr(e, "reason"):
print u"link douban error", e.reason
return None
# 对html代码进行分析,提取电影标题和评分
def getPageItem(self):
pageSource = self.getPageSource()
if not pageSource:
print "load page fail!"
return None
pattern = re.compile('data-title="(.*?)".*data-rate="(.*?)"')
items = re.findall(pattern, pageSource)
count = 1
for item in items:
print count, ":", "[", item[0], "]", "[", item[1], "]"
count = count + 1
# 爬虫
def spider(self):
print "爬取豆瓣热映电影标题和评分"
self.getPageItem()
douban = DouBan()
douban.spider()

运行结果如下:

爬取豆瓣热映电影标题和评分
1 : [ 栀子花开 ] [ 4.2 ]
2 : [ 小时代4:灵魂尽头 ] [ 4.6 ]
3 : [ 西游记之大圣归来 ] [ 8.8 ]
4 : [ 猪猪侠之终极决战 ] [ 3.5 ]
5 : [ 道士下山 ] [ 5.6 ]
6 : [ 杀破狼2 殺破狼2 ] [ 7.6 ]
7 : [ 亲,别怕 ] [ 2.3 ]
8 : [ 张震讲故事之鬼迷心窍 ] [ 3.3 ]

另外,我们也可以使用request和BeautifulSoup库来完成我们的工作,完整的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
# 豆瓣类
class DouBan:
# 初始化方法,定义一些变量
def __init__(self):
self.url = 'http://movie.douban.com/'
# 伪装成浏览器,防止403错误
self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
# 初始化headers
self.headers = {'User-Agent': self.user_agent}
# 获取页面html代码
def get_page_source(self):
# 发起请求
r = requests.get(self.url, headers=self.headers)
# 获取页面html代码
page_source = r.text
# print str(pageSource)
return page_source
# 对html代码进行分析,提取电源标题和评分
def get_page_item(self):
page_source = self.get_page_source()
if not page_source:
print "load page fail!"
return None
# 构建BeautifulSoup对象
soup = BeautifulSoup(page_source, "html.parser")
# 解析网页
list_soup = soup.find_all('li', {'class': 'ui-slide-item'})
file_content = ''
count = 1
# 提取标题和评分
for item in list_soup:
try:
data_title = item.get('data-title') # or item['data-title']
data_rate = item.get('data-rate')
file_content += "%d\t%s\t%s\n" % (count, data_title, data_rate)
count += 1
except Exception as e:
print e
# print "key doesn't exist"
return file_content
# 进行爬虫并保存结果
def spider(self):
print "爬取豆瓣热映电源标题和评分"
file_content = self.get_page_item().encode('utf-8')
f = open('movie_result', 'w')
f.write(file_content)
f.close()
douban = DouBan()
douban.spider()

4. 参考资料

  1. http://cuiqingcai.com/1052.html
  2. http://blog.csdn.net/column/details/why-bug.html
  3. https://github.com/plough/myCrawler/blob/master/doubanBook/book_list_spider.py