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装饰器使用方法实例
Nov 21 Python
python写入xml文件的方法
May 08 Python
python开发之thread实现布朗运动的方法
Nov 11 Python
python 中的int()函数怎么用
Oct 17 Python
python实现换位加密算法的示例
Oct 14 Python
python sqlite的Row对象操作示例
Sep 11 Python
python字符串反转的四种方法详解
Dec 02 Python
python基于opencv检测程序运行效率
Dec 28 Python
keras的ImageDataGenerator和flow()的用法说明
Jul 03 Python
Python Opencv轮廓常用操作代码实例解析
Sep 01 Python
Python实现PIL图像处理库绘制国际象棋棋盘
Jul 16 Python
Python必备技巧之字符数据操作详解
Mar 23 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设计模式 Prototype (原型模式)代码
2011/06/26 PHP
php中防止伪造跨站请求的小招式
2011/09/02 PHP
给WordPress的编辑后台添加提示框的代码实例分享
2015/12/25 PHP
php实现不通过扩展名准确判断文件类型的方法【finfo_file方法与二进制流】
2017/04/18 PHP
Yii框架自定义数据库操作组件示例
2019/11/11 PHP
ASP中用Join和Array,可以加快字符连接速度的代码
2007/08/22 Javascript
用JS写的一个TableView控件代码
2010/01/23 Javascript
JS 事件绑定函数代码
2010/04/28 Javascript
JavaScript实现维吉尼亚(Vigenere)密码算法实例
2013/11/22 Javascript
Node.js中使用事件发射器模式实现事件绑定详解
2014/08/15 Javascript
BootStrap Typeahead自动补全插件实例代码
2016/08/10 Javascript
Node.js中process模块常用的属性和方法
2016/12/13 Javascript
AngularJS select设置默认值的实现方法
2017/08/25 Javascript
JavaScript requestAnimationFrame动画详解
2017/09/14 Javascript
vue实现未登录跳转到登录页面的方法
2018/07/17 Javascript
使用node.js实现微信小程序实时聊天功能
2018/08/13 Javascript
vue.draggable实现表格拖拽排序效果
2018/12/01 Javascript
微信小程序可滑动周日历组件使用详解
2019/10/21 Javascript
浅谈Vuex的this.$store.commit和在Vue项目中引用公共方法
2020/07/24 Javascript
Vue的v-model的几种修饰符.lazy,.number和.trim的用法说明
2020/08/05 Javascript
Python map和reduce函数用法示例
2015/02/26 Python
Python基于回溯法子集树模板解决0-1背包问题实例
2017/09/02 Python
python django使用haystack:全文检索的框架(实例讲解)
2017/09/27 Python
python消除序列的重复值并保持顺序不变的实例
2018/11/08 Python
python plotly绘制直方图实例详解
2019/07/22 Python
Django def clean()函数对表单中的数据进行验证操作
2020/07/09 Python
Python爬虫过程解析之多线程获取小米应用商店数据
2020/11/14 Python
德国亚马逊官方网站:Amazon.de
2020/11/15 全球购物
Final类有什么特点
2012/04/25 面试题
信访工作者先进事迹
2014/01/17 职场文书
电子商务求职信
2014/06/15 职场文书
网吧温馨提示
2015/07/17 职场文书
蓝天保卫战收官在即 :15行业将开展环保分级评价
2019/07/19 职场文书
go语言中json数据的读取和写出操作
2021/04/28 Golang
python实现三阶魔方还原的示例代码
2021/04/28 Python
vue中 this.$set的使用详解
2021/11/17 Vue.js