爬虫的概念其实很简单,指的是抓取网页内容。其实我们在浏览网页的时候,也可以说是在抓取网页内容,而爬虫可以说是程序在抓取网页内容。为什么需要爬虫呢?想象一下,当只有一个网页而内容不多的时候,我们只需要简单地浏览一下就可以得到我们所需要的信息了。但是当网页非常多时,恐怕人工是不能胜任的,这时通过写一个程序访问网页,提取我们所需要的信息,是一件很有意思的事。
用python进行网络爬虫用到的基础库(还有Scrapy这样的高级库)主要有:
网页操作:urllib,urllib2,request
网页解析:BeautifulSoup,lxml
正则表达式:re
爬虫的第一步便是访问网页,获取网页内容,也就是获取网页的源代码。假设我们现在访问的网页是豆瓣主页,在浏览器上,我们可以看到布局清晰的页面,有豆瓣读书,豆瓣电影等模块。我们在网页上点击鼠标右键,选择菜单中的显示网页源代码(或查看源文件等),可以看到网页的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异常等。
当得到网页的源代码后,我们接下来就要对这些代码进行解析了,提取我们想要的内容。我们可以看到网页源代码很繁杂,几乎不知从何入手。幸运的是,我们可以通过一些库来完成我们的提取工作,比如BeautifulSoup,lxml,re等,一些简单的提取可以采用正则表达式来完成,但一般情况下我们会采用BeautifulSoup,lxml等专门的网页解析库。
现在,我们把网页定位到豆瓣电影。
根据前面介绍的方法,我们可以获得网页源代码,现在我们要提取出正在热映的电影标题和评分。我们通过查找,可以发现电影信息出现在如下的标记中:
因此,我们可以构造如下的正则表达式,提取电影标题和评分:
1
|
pattern = re.compile(
'data-title="(.*?)".*data-rate="(.*?)"')
|
在python中使用正则表达式可参考此教程。
我们对上述的代码进行完善,加入身份请求,异常处理等,并写成一个类,代码如下。
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()
|