确定URL格式
我们先观察豆瓣电影Top250任意一页的URL地址的格式。先观察第二页。
可以看到URL地址为: https://movie.douban.com/top250?start=25&filter=.
这一页展示了25条豆瓣影评数据,我们来分析一下这个地址:
- https:// 代表资源传输使用https协议
- movie.douban.com 是豆瓣的二级域名,指向豆瓣的服务器。
- /top250 是服务器的某个资源文件,即豆瓣电影Top250的地址定位符。
- start=25&filter= 是该URL的两个参数,分别代表从多少条记录开始展示和过滤条件。
在实际开发中,为了更好的与开发应用结合,我们一般将URL分为两个部分,一部分是基础部分,是不可变部分,;另一部分为参数部分,是可变部分。
例如,上面的URL可以划分为基础部分:https://movie.douban.com/top250,参数部分:?start=25&filter=
页面抓取
熟悉了URL格式,下面用urllib库试着抓取页面内容
我们以面向对象的编码方式编写这个页面抓取程序。定义一个类名MovieTop,在类中定义一个初始化方法和一个获取页面的方法。
我们把一些基本信息和参数初始化放在类的初始化中,即init方法。另外,获取页面的方法,我们需要知道从第几条记录开始查找、每次查找多少条记录。在这个方法中需要一个循环,通过循环抓取需要的记录。:
#! /usr/bin/python3
#-*- coding:utf-8 -*-
from urllib import request
import re
class MovieTop(object):
def __init__(self):
self.start=0
self.param='&filter='
self.headers={'User-Agent':'Mozilla/5.0(Windows NT 6.1;WOW64)'}
def get_page(self):
page_content=[]
try:
while self.start<=225:
url='https://movie.douban.com/top250?start='+str(self.start)
req=request.Request(url,headers=self.headers)
response=request.urlopen(req)
page=response.read().decode('utf-8')
page_num=(self.start+25)//25
print('正在抓取第'+str(page_num)+'页数据...')
self.start+=25
page_content.append(page)
return page_content
except request.URLError as e:
if hasattr(e,'reason'):
print('抓取失败,失败原因:',e.reason)
def main(self):
print('开始从豆瓣电影抓取数据......')
a=self.get_page()
print('数据抓取完毕...')
在这个初步构建的程序中,我们只指定了一些数据爬取参数,对于爬取的数据并没有做任何处理,也没有保存爬取数据。该程序可以校验该爬虫是否可以正常运行。
提取相关信息
当前我们抓取的数据中有许多HTML格式的文本,需要将其过滤。
Python中的re模块为我们提供了一个compile函数,该函数可以帮我们把正则表达式语法转化为正则表达式对象。
html_text='<p class="name">导演:冯小刚</p>'
reObj=re.compile(u'<p.*?class="name">导演:(.*?)</p>.*?')
print(reObj.findall(html_text))
执行结果:
['冯小刚']
一个更复杂的示例:
html_text='<p class="info">导演:陈凯歌 Kaige Chen '\
'主演:张国荣 Leslie Cheung/ 张丰毅 Fengyi Zha…<br>'\
'1993 / 中国大陆 香港 / 剧情 爱情</p>'
#s='<span>740137人评价</span>'
reObj1=re.compile(u'<p.*?class="info">导演:(.*?)'
+u' (.*?)<br>'
+u'(.*?) / (.*?)'
+u' / (.*?)</p>.*?')
print(reObj.findall(html_text))
程序执行结果:
[('陈凯歌 Kaige Chen', '主演:张国荣 Leslie Cheung/ 张丰毅 Fengyi Zha…', '1993', '中国大陆 香港', '剧情 爱情')]
在MovieTop类中,我们可以通过这种方式从一长串杂乱的HTML文本中提取一些精炼的信息。:
def get_movie_info(set):
pattern=re.compile(u'<div.*?class="item">.*?'……)
……
写入文件
写入文件的过程很简单;
file_top=open(self.file_path,'w',encoding='utf-8')
file_top.write(obj)
我们编写一个方法专门用于文件的写入操作,使得程序面向对象化。在MovieTop类中定义一个方法;
def write_text(self):
print('开始向文件写入数据……')
file_top=open(self.file_path,'w',encoding='utf-8')
……