专栏名称: dwzb
目录
相关文章推荐
卢克文工作室  ·  男人的千年斗争史 ·  昨天  
参考消息  ·  古特雷斯“深感悲伤和震惊” ·  2 天前  
参考消息  ·  肯尼迪遇刺案记录公布 ·  3 天前  
51好读  ›  专栏  ›  dwzb

爬虫代码改进(三)|生成器与类的使用

dwzb  · 掘金  ·  · 2018-04-13 02:18

正文

本文是下面两篇文章的续篇

爬虫基本原理

爬虫代码改进(一)

爬虫代码改进(二)

本系列包括如下内容

  • 抓取豆瓣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,有时候就不要,改一个需求,代码要改的地方很多,这种重新设计是比较低效的。







请到「今天看啥」查看全文