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使用Flask框架同时上传多个文件的方法
Mar 21 Python
Python实现1-9数组形成的结果为100的所有运算式的示例
Nov 03 Python
Python基于OpenCV库Adaboost实现人脸识别功能详解
Aug 25 Python
python导入坐标点的具体操作
May 10 Python
python文件写入write()的操作
May 14 Python
对Python中画图时候的线类型详解
Jul 07 Python
python对绑定事件的鼠标、按键的判断实例
Jul 17 Python
Python中typing模块与类型注解的使用方法
Aug 05 Python
使用Python和OpenCV检测图像中的物体并将物体裁剪下来
Oct 30 Python
Python基于Tensor FLow的图像处理操作详解
Jan 15 Python
Python关键字及可变参数*args,**kw原理解析
Apr 04 Python
python实现图像高斯金字塔的示例代码
Dec 11 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/06/19 PHP
微信支付开发维权通知实例
2016/07/12 PHP
php rsa 加密,解密,签名,验签详解
2016/12/06 PHP
FusionCharts图表显示双Y轴双(多)曲线
2012/11/22 Javascript
js设置document.domain实现跨域的注意点分析
2015/05/21 Javascript
快速掌握Node.js模块封装及使用
2016/03/21 Javascript
Angularjs使用directive自定义指令实现attribute继承的方法详解
2016/08/05 Javascript
不使用script导入js文件的几种方法
2016/10/27 Javascript
vue2.0中goods选购栏滚动算法的实现代码
2017/05/17 Javascript
Angularjs 实现动态添加控件功能
2017/05/25 Javascript
JavaScript基于数组实现的栈与队列操作示例
2018/12/22 Javascript
详解vuex的简单todolist例子
2019/07/14 Javascript
微信小程序实现语音识别转文字功能及遇到的坑
2019/08/02 Javascript
12 种使用Vue 的最佳做法
2020/03/30 Javascript
使用JavaScript实现贪吃蛇游戏
2020/09/29 Javascript
用Python实现web端用户登录和注册功能的教程
2015/04/30 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
python3基于OpenCV实现证件照背景替换
2018/07/18 Python
用Python实现读写锁的示例代码
2018/11/05 Python
python3对接mysql数据库实例详解
2019/04/30 Python
Python使用itchat模块实现简单的微信控制电脑功能示例
2019/08/26 Python
Python连接SQLite数据库并进行增册改查操作方法详解
2020/02/18 Python
python实现简单坦克大战
2020/03/27 Python
matplotlib自定义鼠标光标坐标格式的实现
2021/01/08 Python
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
法雷奥SQA(electric)面试问题
2016/01/23 面试题
开办加工厂创业计划书
2014/01/03 职场文书
大学旷课检讨书
2014/01/28 职场文书
2014年教师党员公开承诺书
2014/05/28 职场文书
医院保洁服务方案
2014/06/11 职场文书
2014年自愿离婚协议书范本
2014/09/25 职场文书
会计专业求职信范文
2015/03/19 职场文书
2015年新教师工作总结
2015/04/28 职场文书
房产电话营销开场白
2015/05/29 职场文书
致短跑运动员加油稿
2015/07/21 职场文书
Go 自定义package包设置与导入操作
2021/05/06 Golang