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使用正则表达式检测密码强度源码分享
Jun 11 Python
Python实现备份文件实例
Sep 16 Python
Python面向对象之接口、抽象类与多态详解
Aug 27 Python
Python中出现IndentationError:unindent does not match any outer indentation level错误的解决方法
Apr 18 Python
浅谈Python的条件判断语句if/else语句
Mar 21 Python
python 实现的发送邮件模板【普通邮件、带附件、带图片邮件】
Jul 06 Python
Python全栈之列表数据类型详解
Oct 01 Python
使用python远程操作linux过程解析
Dec 04 Python
使用python matploblib库绘制准确率,损失率折线图
Jun 16 Python
Python读取yaml文件的详细教程
Jul 21 Python
python进行二次方程式计算的实例讲解
Dec 06 Python
python实现高效的遗传算法
Apr 07 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利用COM对象访问SQLServer、Access
2006/10/09 PHP
彻底杜绝PHP的session cookie错误
2009/08/09 PHP
浅析51个PHP处理字符串的函数
2013/08/02 PHP
php设计模式之享元模式分析【星际争霸游戏案例】
2020/03/23 PHP
JS比较2个日期间隔的示例代码
2014/04/15 Javascript
JavaScript简单修改窗口大小的方法
2015/08/03 Javascript
深入解析JavaScript中的立即执行函数
2016/05/21 Javascript
基于JavaScript实现购物网站商品放大镜效果
2016/09/06 Javascript
JQuery Ajax WebService传递参数的简单实例
2016/11/02 Javascript
EasyUI 结合JS导出Excel文件的实现方法
2016/11/10 Javascript
JavaScript canvas实现围绕旋转动画
2017/11/18 Javascript
浅谈React中的元素、组件、实例和节点
2018/02/27 Javascript
vue动态路由:路由参数改变,视图不更新问题的解决
2019/11/05 Javascript
如何实现echarts markline标签名显示自己想要的
2020/07/20 Javascript
Vue使用Element实现增删改查+打包的步骤
2020/11/25 Vue.js
python构造icmp echo请求和实现网络探测器功能代码分享
2014/01/10 Python
Python环境变量设置方法
2016/08/28 Python
python中MethodType方法介绍与使用示例
2017/08/03 Python
Python实现的求解最小公倍数算法示例
2018/05/03 Python
Python OpenCV处理图像之图像直方图和反向投影
2018/07/10 Python
在Python中实现替换字符串中的子串的示例
2018/10/31 Python
Python Pillow Image Invert
2019/01/22 Python
Python3内置模块之base64编解码方法详解
2019/07/13 Python
基于Tensorflow高阶读写教程
2020/02/10 Python
Keras官方中文文档:性能评估Metrices详解
2020/06/15 Python
全球速卖通法国在线交易平台:AliExpress法国
2017/07/07 全球购物
澳大利亚领先的在线葡萄酒零售商:Get Wines Direct
2018/03/27 全球购物
关于迟到的检讨书
2014/01/26 职场文书
安踏广告词改编版
2014/03/21 职场文书
入党积极分子批评与自我批评思想汇报
2014/09/14 职场文书
超市食品安全承诺书
2015/04/29 职场文书
MySQL 如何分析查询性能
2021/05/12 MySQL
SqlServer数据库远程连接案例教程
2021/07/15 SQL Server
国庆节到了,利用JS实现一个生成国庆风头像的小工具 详解实现过程
2021/10/05 Javascript
Python通过loop.run_in_executor执行同步代码 同步变为异步
2022/04/11 Python
springboot读取nacos配置文件
2022/05/20 Java/Android