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中的错误处理
Apr 10 Python
Python 爬虫学习笔记之正则表达式
Sep 21 Python
Python编程实现微信企业号文本消息推送功能示例
Aug 21 Python
Python实现模拟分割大文件及多线程处理的方法
Oct 10 Python
详解配置Django的Celery异步之路踩坑
Nov 25 Python
Python查找最长不包含重复字符的子字符串算法示例
Feb 13 Python
python中用logging实现日志滚动和过期日志删除功能
Aug 20 Python
Cython编译python为so 代码加密示例
Dec 23 Python
pycharm全局搜索的具体步骤
Jul 28 Python
python中的列表和元组区别分析
Dec 30 Python
使用pandas或numpy处理数据中的空值(np.isnan()/pd.isnull())
May 14 Python
django中websocket的具体使用
Jan 22 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
中国广播史趣谈 — 几个历史第一次
2021/03/01 无线电
frename PHP 灵活文件命名函数 frename
2009/09/09 PHP
php计算十二星座的函数代码
2012/08/21 PHP
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
PHP实现无限级分类(不使用递归)
2015/10/22 PHP
php微信开发自定义菜单
2016/08/27 PHP
PHP实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
php封装实现钉钉机器人报警接口的示例代码
2020/08/08 PHP
编写跨浏览器的javascript代码必备[js多浏览器兼容写法]
2008/10/29 Javascript
javascript显示用户停留时间的简单实例
2013/08/05 Javascript
jquery中each方法示例和常用选择器
2014/07/08 Javascript
JavaScript截取字符串的2个函数介绍
2014/08/27 Javascript
详解JavaScript中的forEach()方法的使用
2015/06/08 Javascript
jquery validate.js表单验证入门实例(附源码)
2015/11/10 Javascript
jQuery实现的文字hover颜色渐变效果实例
2016/02/20 Javascript
javascript js 操作数组 增删改查的简单实现
2016/06/20 Javascript
AngularJS实现与Java Web服务器交互操作示例【附demo源码下载】
2016/11/02 Javascript
详解Angular-cli生成组件修改css成less或sass的实例
2017/07/27 Javascript
详解Vue、element-ui、axios实现省市区三级联动
2019/05/07 Javascript
Vue项目中使用jquery的简单方法
2019/05/16 jQuery
判断“命令按钮”是否被鼠标单击详解
2019/07/31 Javascript
《javascript设计模式》学习笔记七:Javascript面向对象程序设计组合模式详解
2020/04/08 Javascript
Python 文件处理注意事项总结
2017/04/10 Python
Python之NumPy(axis=0 与axis=1)区分详解
2019/05/27 Python
简单了解Python3 bytes和str类型的区别和联系
2019/12/19 Python
TripAdvisor斯洛伐克:阅读评论、比较价格和酒店预订
2018/04/25 全球购物
prAna官网:瑜伽、旅行和冒险服装
2019/03/10 全球购物
美国折扣香水网站:The Perfume Spot
2020/12/12 全球购物
请解释一下webService? 如何用.net实现webService
2014/06/09 面试题
毕业生优秀推荐信
2013/11/26 职场文书
中专生自我鉴定范文
2014/02/02 职场文书
幼儿园教学随笔感言
2014/02/23 职场文书
法人授权委托书范本
2014/09/17 职场文书
校长个人总结
2015/03/03 职场文书
2016年乡镇综治宣传月活动总结
2016/03/16 职场文书
SpringBoot项目中控制台日志的保存配置操作
2021/06/18 Java/Android