Python多线程爬取豆瓣影评API接口


Posted in Python onOctober 22, 2019

爬虫库

使用简单的requests库,这是一个阻塞的库,速度比较慢。

解析使用XPATH表达式

总体采用类的形式

多线程

使用concurrent.future并发模块,建立线程池,把future对象扔进去执行即可实现并发爬取效果

数据存储

使用Python ORM sqlalchemy保存到数据库,也可以使用自带的csv模块存在CSV中。

API接口

因为API接口存在数据保护情况,一个电影的每一个分类只能抓取前25页,全部评论、好评、中评、差评所有分类能爬100页,每页有20个数据,即最多为两千条数据。

因为时效性原因,不保证代码能爬到数据,只是给大家一个参考思路,上代码:

from datetime import datetime
import random
import csv
from concurrent.futures import ThreadPoolExecutor, as_completed

from lxml import etree
import pymysql
import requests

from models import create_session, Comments

#随机UA
USERAGENT = [
  'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
  'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
  'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
  'Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50',
  'Mozilla/5.0 (Windows; U; Windows NT 6.1; ) AppleWebKit/534.12 (KHTML, like Gecko) Maxthon/3.0 Safari/534.12'
]


class CommentFetcher:
  headers = {'User-Agent': ''}
  cookie = ''
  cookies = {'cookie': cookie}
  # cookie为登录后的cookie,需要自行复制
  base_node = '//div[@class="comment-item"]'


  def __init__(self, movie_id, start, type=''):
    '''
    :type: 全部评论:'', 好评:h 中评:m 差评:l
    :movie_id: 影片的ID号
    :start: 开始的记录数,0-480
    '''
    self.movie_id = movie_id
    self.start = start
    self.type = type
    self.url = 'https://movie.douban.com/subject/{id}/comments?start={start}&limit=20&sort=new_score\&status=P&percent_type={type}&comments_only=1'.format(
      id=str(self.movie_id),
      start=str(self.start),
      type=self.type
    )
    #创建数据库连接
    self.session = create_session()

  #随机useragent
  def _random_UA(self):
    self.headers['User-Agent'] = random.choice(USERAGENT)


  #获取api接口,使用get方法,返回的数据为json数据,需要提取里面的HTML
  def _get(self):
    self._random_UA()
    res = ''
    try:
      res = requests.get(self.url, cookies=self.cookies, headers=self.headers)
      res = res.json()['html']
    except Exception as e:
      print('IP被封,请使用代理IP')
    print('正在获取{} 开始的记录'.format(self.start))
    return res

  def _parse(self):
    res = self._get()
    dom = etree.HTML(res)

    #id号
    self.id = dom.xpath(self.base_node + '/@data-cid')
    #用户名
    self.username = dom.xpath(self.base_node + '/div[@class="avatar"]/a/@title')
    #用户连接
    self.user_center = dom.xpath(self.base_node + '/div[@class="avatar"]/a/@href')
    #点赞数
    self.vote = dom.xpath(self.base_node + '//span[@class="votes"]/text()')
    #星级
    self.star = dom.xpath(self.base_node + '//span[contains(@class,"rating")]/@title')
    #发表时间
    self.time = dom.xpath(self.base_node + '//span[@class="comment-time "]/@title')
    #评论内容 所有span标签class名为short的节点文本
    self.content = dom.xpath(self.base_node + '//span[@class="short"]/text()')

  #保存到数据库
  def save_to_database(self):
    self._parse()
    for i in range(len(self.id)):
      try:
        comment = Comments(
          id=int(self.id[i]),
          username=self.username[i],
          user_center=self.user_center[i],
          vote=int(self.vote[i]),
          star=self.star[i],
          time=datetime.strptime(self.time[i], '%Y-%m-%d %H:%M:%S'),
          content=self.content[i]
        )

        self.session.add(comment)
        self.session.commit()
        return 'finish'


      except pymysql.err.IntegrityError as e:
        print('数据重复,不做任何处理')

      except Exception as e:
        #数据添加错误,回滚
        self.session.rollback()

      finally:
        #关闭数据库连接
        self.session.close()

  #保存到csv
  def save_to_csv(self):
    self._parse()
    f = open('comment.csv', 'w', encoding='utf-8')
    csv_in = csv.writer(f, dialect='excel')
    for i in range(len(self.id)):
      csv_in.writerow([
        int(self.id[i]),
        self.username[i],
        self.user_center[i],
        int(self.vote[i]),
        self.time[i],
        self.content[i]
      ])
    f.close()


if __name__ == '__main__':
  with ThreadPoolExecutor(max_workers=4) as executor:
    futures = []
    for i in ['', 'h', 'm', 'l']:
      for j in range(25):
        fetcher = CommentFetcher(movie_id=26266893, start=j * 20, type=i)
        futures.append(executor.submit(fetcher.save_to_csv))

    for f in as_completed(futures):
      try:
        res = f.done()
        if res:
          ret_data = f.result()
          if ret_data == 'finish':
            print('{} 成功保存数据'.format(str(f)))
      except Exception as e:
        f.cancel()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中给List添加元素的4种方法分享
Nov 28 Python
Python简单实现控制电脑的方法
Jan 22 Python
python DataFrame获取行数、列数、索引及第几行第几列的值方法
Apr 08 Python
Python Numpy库安装与基本操作示例
Jan 08 Python
Python之修改图片像素值的方法
Jul 03 Python
python增加图像对比度的方法
Jul 12 Python
pandas 选取行和列数据的方法详解
Aug 08 Python
对python 树状嵌套结构的实现思路详解
Aug 09 Python
使用pyinstaller逆向.pyc文件
Dec 20 Python
Python操作MongoDb数据库流程详解
Mar 05 Python
PYQT5 vscode联合操作qtdesigner的方法
Mar 24 Python
Python文件的操作示例的详细讲解
Apr 08 Python
Python Process多进程实现过程
Oct 22 #Python
详解python中eval函数的作用
Oct 22 #Python
FFT快速傅里叶变换的python实现过程解析
Oct 21 #Python
python 采用paramiko 远程执行命令及报错解决
Oct 21 #Python
python文件读写代码实例
Oct 21 #Python
python 动态调用函数实例解析
Oct 21 #Python
python 两个数据库postgresql对比
Oct 21 #Python
You might like
PHP的变量总结 新手推荐
2011/04/18 PHP
php实现数组按指定KEY排序的方法
2015/03/30 PHP
PHP实现简单爬虫的方法
2015/07/29 PHP
基于PHP实现简单的随机抽奖小程序
2016/01/05 PHP
Yii2中如何使用modal弹窗(基本使用)
2016/05/30 PHP
PHP实现针对日期,月数,天数,周数,小时,分,秒等的加减运算示例【基于strtotime】
2017/04/19 PHP
PHP中模糊查询并关联三个select框
2017/06/19 PHP
jquery DOM操作 基于命令改变页面
2010/05/06 Javascript
javascript学习笔记(八) js内置对象
2012/06/19 Javascript
JavaScript中DOM详解
2015/04/13 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
基于Bootstrap里面的Button dropdown打造自定义select
2016/05/30 Javascript
jQuery和JavaScript节点插入元素的方法对比
2016/11/18 Javascript
VUE开发一个图片轮播的组件示例代码
2017/03/06 Javascript
Angularjs 实现移动端在线测评效果(推荐)
2017/04/05 Javascript
浅谈vue-lazyload实现的详细过程
2017/08/22 Javascript
简单了解node npm cnpm的具体使用方法
2019/02/27 Javascript
vue点击标签切换选中及互相排斥操作
2020/07/17 Javascript
wxPython中文教程入门实例
2014/06/09 Python
Python类的定义、继承及类对象使用方法简明教程
2015/05/08 Python
python中模块查找的原理与方法详解
2017/08/11 Python
修改python plot折线图的坐标轴刻度方法
2018/12/13 Python
Python实现京东秒杀功能代码
2019/05/16 Python
Python调用Redis的示例代码
2020/11/24 Python
Ted Baker英国官网:男士和女士服装及配件
2017/03/13 全球购物
以设计师精品品质提供快速时尚:PopJulia
2018/01/09 全球购物
法国包包和行李箱销售网站:Bagage24.fr
2020/03/24 全球购物
internal修饰符起什么作用
2013/12/16 面试题
党建示范点实施方案
2014/03/12 职场文书
机关作风整顿个人剖析材料
2014/10/06 职场文书
保密工作整改报告
2014/11/06 职场文书
社区党建工作总结2015
2015/05/13 职场文书
小孩不笨观后感
2015/06/03 职场文书
基层医务人员三严三实心得体会
2016/01/05 职场文书
六种css3实现的边框过渡效果
2021/04/22 HTML / CSS
MyBatis配置文件解析与MyBatis实例演示
2022/04/07 Java/Android