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通过openpyxl生成Excel文件的方法
May 12 Python
Python函数式编程指南(二):从函数开始
Jun 24 Python
Python自定义主从分布式架构实例分析
Sep 19 Python
利用python实现xml与数据库读取转换的方法
Jun 17 Python
解决python使用open打开文件中文乱码的问题
Dec 29 Python
python矩阵的转置和逆转实例
Dec 12 Python
对Python3 pyc 文件的使用详解
Feb 16 Python
tensorflow实现测试时读取任意指定的check point的网络参数
Jan 21 Python
python内打印变量之%和f的实例
Feb 19 Python
Selenium alert 弹窗处理的示例代码
Aug 06 Python
解决python便携版无法直接运行py文件的问题
Sep 01 Python
python 获取剪切板内容的两种方法
Nov 28 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的多进程编程方法
2015/08/18 PHP
php自定义分页类完整实例
2015/12/25 PHP
Javascript 网页黑白效果实现代码(兼容IE/FF等)
2010/04/23 Javascript
javascript的alert box在java中如何显示多行
2014/05/18 Javascript
js中实现多态采用和继承类似的方法
2014/08/22 Javascript
详谈javascript异步编程
2016/02/21 Javascript
HTML5 canvas 9绘制图片实例详解
2016/09/06 Javascript
javascript的document中的动态添加标签实现方法
2016/10/24 Javascript
JS弹出窗口的运用与技巧大全
2016/11/01 Javascript
vue-cli 自定义指令directive 添加验证滑块示例
2017/10/19 Javascript
JS实现不用中间变量temp 实现两个变量值得交换方法
2018/02/04 Javascript
js如何获取图片url的Blob值并预览示例代码
2019/03/07 Javascript
解决JQuery的ajax函数执行失败alert函数弹框一闪而过问题
2019/04/10 jQuery
JavaScript判断浏览器运行环境的详细方法
2019/06/30 Javascript
小程序采集录音并上传到后台
2019/11/22 Javascript
修改vue源码实现动态路由缓存的方法
2020/01/21 Javascript
[01:16:50]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第一场 3月7日
2021/03/11 DOTA
快速排序的算法思想及Python版快速排序的实现示例
2016/07/02 Python
python3+selenium自动化测试框架详解
2019/03/17 Python
详解Django项目中模板标签及模板的继承与引用(网站中快速布置广告)
2019/03/27 Python
使用Python进行体育竞技分析(预测球队成绩)
2019/05/16 Python
Python变量访问权限控制详解
2019/06/29 Python
python word转pdf代码实例
2019/08/16 Python
在python中计算ssim的方法(与Matlab结果一致)
2019/12/19 Python
Python Django form 组件动态从数据库取choices数据实例
2020/05/19 Python
css3学习系列之移动属性详解
2017/07/04 HTML / CSS
英国领先的男装设计师服装购物网站:Mainline Menswear
2018/02/04 全球购物
Juicy Couture Beauty官方网站:香水和化妆品
2019/03/12 全球购物
个人素质的自我评价分享
2013/12/16 职场文书
会计出纳岗位职责
2013/12/25 职场文书
小学红领巾中秋节广播稿
2014/01/13 职场文书
大学生自我鉴定书
2014/03/24 职场文书
考试作弊检讨书1000字(5篇)
2014/10/19 职场文书
优秀家长事迹材料(2016推荐版)
2016/02/29 职场文书
公司要求试用期员工提交“述职报告”,该怎么写?
2019/07/17 职场文书
Python控制台输出俄罗斯方块的方法实例
2021/04/17 Python