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抓取豆瓣图片并自动保存示例学习
Jan 10 Python
python anaconda 安装 环境变量 升级 以及特殊库安装的方法
Jun 21 Python
python使用xslt提取网页数据的方法
Feb 23 Python
Python实现按中文排序的方法示例
Apr 25 Python
Python threading的使用方法解析
Aug 28 Python
使用python制作一个解压缩软件
Nov 13 Python
Tensorflow 模型转换 .pb convert to .lite实例
Feb 12 Python
对Python中 \r, \n, \r\n的彻底理解
Mar 06 Python
浅析python标准库中的glob
Mar 13 Python
Python Tornado批量上传图片并显示功能
Mar 26 Python
keras训练曲线,混淆矩阵,CNN层输出可视化实例
Jun 15 Python
python绘制趋势图的示例
Sep 17 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 at(@)符号的用法简介
2009/07/11 PHP
用sql命令修改数据表中的一个字段为非空(not null)的语句
2010/06/04 PHP
使用php记录用户通过搜索引擎进网站的关键词
2014/02/13 PHP
PHP异常Parse error: syntax error, unexpected T_VAR错误解决方法
2014/05/06 PHP
ThinkPHP查询语句与关联查询用法实例
2014/11/01 PHP
Linux下从零开始安装配置Nginx服务器+PHP开发环境
2015/12/21 PHP
解决PHP 7编译安装错误:cannot stat ‘phar.phar’: No such file or directory
2017/02/25 PHP
Yii2语言国际化自动配置详解
2018/08/22 PHP
Prototype使用指南之dom.js
2007/01/10 Javascript
RGB颜色值转HTML十六进制(HEX)代码的JS函数
2009/04/25 Javascript
JS input 数字验证代码
2009/07/30 Javascript
Jquery图形报表插件 jqplot简介及参数详解
2012/10/10 Javascript
针对JavaScript中this指向的简单理解
2016/08/26 Javascript
js 中rewrap-ajax.js插件实例代码
2017/10/20 Javascript
vue实现表格过滤功能
2019/09/27 Javascript
在vue中动态添加class类进行显示隐藏实例
2019/11/09 Javascript
Python中的ctime()方法使用教程
2015/05/22 Python
在Django中编写模版节点及注册标签的方法
2015/07/20 Python
简单学习Python time模块
2016/04/29 Python
python用户管理系统的实例讲解
2017/12/23 Python
详解TensorFlow查看ckpt中变量的几种方法
2018/06/19 Python
python 除法保留两位小数点的方法
2018/07/16 Python
python实现飞机大战
2018/09/11 Python
基于wxPython的GUI实现输入对话框(2)
2019/02/27 Python
python实现ssh及sftp功能(实例代码)
2020/03/16 Python
pandas中的ExcelWriter和ExcelFile的实现方法
2020/04/24 Python
HTML5 Canvas 绘图——使用 Canvas 绘制图形图文教程 使用html5 canvas 绘制精美的图
2015/08/31 HTML / CSS
html5拖拽应用记录及注意点
2020/05/27 HTML / CSS
应届生保险求职信
2013/11/11 职场文书
教师的实习鉴定
2013/12/15 职场文书
幼儿园教师奖惩制度
2014/02/01 职场文书
2014年保育员个人工作总结
2014/12/02 职场文书
大学生社会服务心得体会
2016/01/22 职场文书
mysql部分操作
2021/04/05 MySQL
JavaScript原始值与包装对象的详细介绍
2021/05/11 Javascript
一篇文章了解正则表达式的替换技巧
2022/02/24 Javascript