Python多线程豆瓣影评API接口爬虫
爬虫库
使用简单的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多线程豆瓣影评API接口爬虫的更多相关文章
- 用Python调用华为云API接口发短信
[摘要] 用Python调用华为云API接口实现发短信,当然能给调用发短信接口前提条件是通过企业实名认证,而且有一个通过审核的短信签名,话不多说,showcode #!/usr/bin/python3 ...
- python使用zabbix的API接口
一.实验环境 python3.6.6 zabbix 3.0.9 二.实验目的 了解Zabbix的API接口格式 通过python实现登陆zabbix服务,获得登陆token 通过python检索zab ...
- python访问cloudstack的api接口
1.CloudStack API 如同 AWS API 一样,CloudStack API 也是基于 Web Service,可以使用任何一种支持 HTTP 调用的语言(例如 Java,python, ...
- Java多线程:实现API接口创建线程方式详解
先看例子: /**实现Runnable接口创建线程步骤: * 1.创建一个实现Runnable接口的类 * 2.重写Runnable类中抽象的run()方法 * 3.创建实现类的对象 * 4.声明Th ...
- 简单实现Python调用有道API接口(最新的)
# ''' # Created on 2018-5-26 # # @author: yaoshuangqi # ''' import urllib.request import urllib.pars ...
- Python实现简单的API接口
get方法 代码实现 # coding:utf-8 import json from urlparse import parse_qs from wsgiref.simple_ ...
- 利用python多线程模块实现模拟接口并发
import requestsimport jsonimport threadingimport timeimport uuid class postrequests(): def __init__( ...
- python 多线程,多进程,高效爬虫
1.多线程from concurrent.futures import ThreadPoolExecutor import requests def fetch_async(url): respons ...
- 使用Python解析豆瓣上Json格式数据
现在的API接口多为xml或json,json解析更简洁相对xml来说 以豆瓣的API接口为例,解析返回的json数据: https://api.douban.com/v2/book/1220562 ...
随机推荐
- bzoj 2242: [SDOI2011]计算器【扩展欧几里得+快速幂+BSGS】
第一问快速幂板子 第二问把式子转化为\( xy\equiv Z(mod P)\rightarrow xy+bP=z \),然后扩展欧几里得 第三问BSGS板子 #include<iostream ...
- Tensor Operation
Main operation categories that encompass the operations of tensors. Reshaping operations Element-wis ...
- RT-Thread 设备驱动ADC浅析与改进
OS版本:RT-Thread 4.0.0 芯片:STM32F407 下面时官方ADC提供的参考访问接口 访问 ADC 设备 应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC ...
- 例题3-4 master-mind hints
下面先附上我的水货代码,,,,一会附上,,,刘大婶给的代码///////3ms #include<stdio.h> #include<string.h> int main() ...
- python爬虫抓取哈尔滨天气信息(静态爬虫)
python 爬虫 爬取哈尔滨天气信息 - http://www.weather.com.cn/weather/101050101.shtml 环境: windows7 python3.4(pip i ...
- .NET框架概述
.NET战略目标: 任何时候(when),任何地方(where),使用任何工具(what)都能通过.NET的服务获得网络上的任何信息. .NET优势: 1.提供了一个面向对象的编程环境,完全支持面向对 ...
- RabbitMQ五:生产者--队列--多消费者
一.生成者-队列-多消费者(前言) 上篇文章,我们做了一个简单的Demo,一个生产者对应一个消费者,本篇文章就介绍 生产者-队列-多个消费者,下面简单示意图 P 生产者 C 消费者 中间队列 ...
- struts 2.5 There is no Action mapped for namespace [/] and action name [user_find] associated with context path [/struts2_crm].
遇到了这个错误. There is no Action mapped for namespace [/] and action name [user_find] associated with con ...
- Nginx反向代理node,实现让静态文件在同一域
Nginx反向代理node,实现让静态文件在同一域 原文https://github.com/zhuangZhou/Blog/issues/4 不管是Vue还是React,还是传统的网站,与node服 ...
- 《基于Node.js实现简易聊天室系列之引言》
简述:这个聊天室是基于Node.js实现的,完成了基本的实时通信功能.在此之前,对node.js和mongodb一无所知,但是通过翻阅博客,自己动手基本达到了预期的效果.技术,不应该是闭门造车,而是学 ...