正文
本文是下面两篇文章的续篇
爬虫基本原理
爬虫代码改进(一)
爬虫代码改进(二)
本系列包括如下内容
-
抓取豆瓣top250一页多个字段
-
整合成列表
-
存储为json文件
-
定义成函数形式
-
多页抓取之构造url
-
多页抓取之翻页
-
抓取二级页面数据
-
通过生成器优化代码
-
改写为类的形式
本文主要讲
通过生成器优化代码
使用生成器可以大大改进代码的可扩展性,比如下面我们将抓取一级页面250个电影信息,翻页方法使用生成器改写为
import requests # 导入网页请求库
from bs4 import BeautifulSoup # 导入网页解析库
import json
def start_requests(url):
r = requests.get(url)
return r.content
def parse(text):
soup = BeautifulSoup(text, 'html.parser')
movie_list = soup.find_all('div', class_ = 'item')
for movie in movie_list:
mydict = {}
mydict['title'] = movie.find('span', class_ = 'title').text
mydict['score'] = movie.find('span', class_ = 'rating_num').text
quote = movie.find('span', class_ = 'inq')
mydict['quote'] = quote.text if quote else None
star = movie.find('div', class_ = 'star')
mydict['comment_num'] = star.find_all('span')[-1].text[:-3]
yield mydict # 这里使用生成器
def get_all(): # 获取所有页封装成一个函数
for i in range(2):
url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25)
text = start_requests(url)
result = parse(text)
yield from result # 返回一个生成器
对
yield
和
yield from
没有了解的读者可以先看
这篇文章
这样做的好处是扩展性很好,
get_all()
的结果就是一个包含所有信息的生成器,只要一个循环就可以自由调用所有抓取到的信息。而且生成器的特性是调用时才会运行,所以相当于每次抓取到信息就直接一步到位输出到自己想要的位置,而没有了 中间先存储一步,再提取 的资源浪费。
当你要print时,只需要
def main():
for info in get_all():
print(info)
if __name__ == '__main__':
main()
当你需要存到list,再存成json文件时可以
def main():
result_list = list(get_all())
s = json.dumps(result_list, indent = 4, ensure_ascii=False)
with open('movies.json', 'w', encoding = 'utf-8') as f:
f.write(s)
if __name__ == '__main__':
main()
当你需要每一条存储到数据库的时候,可以
def main():
for info in get_all():
put_into_database_code
if __name__ == '__main__':
main()
可以想象如果不使用生成器需要怎么做,有时候要构造一个list,有时候就不要,改一个需求,代码要改的地方很多,这种重新设计是比较低效的。