目标是爬取豆瓣电影分类排行榜的前n页,由用户输入页数
一、函数封装
之前写的代码都是零散的,利用这次案例我们也进行一下函数的封装。
每次开启一个程序,都必须写一个主函数作为程序的入口,也就是我们常说的main函数。以下是python主函数的写法
if __name__ == '__main__':
之后我们让用户输入起始页面和结束页面,然后对每一个页面执行GET请求的三部曲:
- 请求对象的定制
- 获取响应的数据
- 下载数据
if __name__ == '__main__':
start_page = int(input('起始页面'))
end_page = int(input('结束页面'))
for page in range(start_page, end_page + 1):
request = create_request(page)
content = get_content(request)
download(page, content)
二、请求对象的定制
首先需要获取url
以动作电影排行榜为例,F12寻找数据接口,如图。并且发现url中的start和limit参数分别代表起始数量和每页电影数。例如start=0&limit=20就代表从第1个电影开始,此页显示20个电影。那我们修改start为20就可以从第21名的电影开始抓取数据。
create_request()函数代码如下:
def create_request(start):
base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
data = {
'start': (start - 1) * 20,
'limit': 20
}
url = base_url + urllib.parse.urlencode(data)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/98.0.4758.102 Safari/537.36 "
}
_request = urllib.request.Request(url=url, headers=headers)
return _request
需要记住:
- url中删掉后面的参数,创建data字典并使用urlencode()方法动态拼接url
- 需要headers请求头模拟浏览器破解反爬,还不行就把Cookie也加上
三、获取响应的数据
将上一步定制的request作为get_content()的参数
def get_content(_request):
res = urllib.request.urlopen(_request)
_content = res.read().decode('utf-8')
return _content
需要记住:
- urlopen返回的是一个响应,还需要read()来读取数据
- 记得要decode为utf-8格式,否则结果是看不懂的
四、下载数据
def download(_page, _content):
with open('douban' + str(_page) + '.json', 'w', encoding='utf-8') as f:
f.write(_content)
需要记住:
- 用with方法打开文件会自动关闭,不用手动再去写f.close,推荐!
- 打开文件也要指定encoding为’utf-8’格式,不过默认就是如此
五、完整代码
参数前面加了_是为了区分形参和实参
import urllib.request
import urllib.parse
def create_request(start):
base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
data = {
'start': (start - 1) * 20,
'limit': 20
}
url = base_url + urllib.parse.urlencode(data)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/98.0.4758.102 Safari/537.36 "
}
_request = urllib.request.Request(url=url, headers=headers)
return _request
def get_content(_request):
res = urllib.request.urlopen(_request)
_content = res.read().decode('utf-8')
return _content
def download(_page, _content):
with open('douban' + str(_page) + '.json', 'w', encoding='utf-8') as f:
f.write(_content)
if __name__ == '__main__':
start_page = int(input('起始页面'))
end_page = int(input('结束页面'))
for page in range(start_page, end_page + 1):
request = create_request(page)
content = get_content(request)
download(page, content)
运行程序,例如输入1和2。(不敢输入太大的数,怕被封IP)
稍等片刻后文件目录下出现了我们的下载文件,douban1.json即第一页前20名电影的所有数据
小技巧,文件内容都在一行之中,按住CTRL + ALT + L可以转换为如下图格式。但要避免快捷键冲突,例如开着QQ会锁定QQ账号。。关闭QQ即可解决冲突。
总结
- 写主函数 if name == ‘main’:
- GET请求三部曲:请求对象定制,获取响应数据,下载数据。
- GET请求的参数data不需要编码
- CTRL + ALT + L可以让json文件更规整