由于豆瓣在今年5月份已经禁止展示所有短评,只展示最热的500条数据,并且在爬取到240条的时候,如果没有登录的话,会提示登录。
因此几天的爬虫,包括豆瓣的自动登录和数据爬取后批量存入pymysql数据库。

在这个爬虫完成后,其实我也在页面上找了下,在全部评论里还是能看到带有页数分页的评论的,在下面代码的基础上修改下路径和爬取数据的逻辑,其实也是能爬取的。

本文是基于scrapy框架,python 3.x下完成的。爬取了9月3日前碟中谍6的最热短评数据
这是爬虫文件结构:

这是爬取的数据截图:

下面上代码:
dzd-content

# -*- coding: utf-8 -*-
import scrapy
from dzd.items import DzdItem
import time
import random
from faker import Factory
from urllib import parsef = Factory.create()class DzdContentSpider(scrapy.Spider):name = 'dzd'allowed_domains = ['movie.douban.com']#构建豆瓣的登陆数据,详细的数据豆瓣可能会根据时间不同,修改相关的一些字段,但登陆的账号和密码是不会变的formdata = {'source': 'index_nav',# 'redir': 'https://www.douban.com',# 'login': '登录','form_email': '你的账号','form_password': '你的密码'}
#构建访问的头文件headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Encoding': 'gzip, deflate, br','Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3','Connection': 'keep-alive',#使用faker中的Factory,动态生成不同的userAgent'User-Agent': f.user_agent()}
#重写了start_request方法def start_requests(self):print('------爬取开始--------')
#豆瓣有大量数据观看后的屏蔽策略,需要登录,所以要从一开始访问就要带上cookie进行访问return [scrapy.Request(url='https://www.douban.com/accounts/login',headers=self.headers,meta={'cookiejar': 1},callback=self.parse_login)]def parse_login(self, response):# 获取登录页面是否有验证码img_url = response.xpath('//img[@class="captcha_image"]/@src').extract_first()if img_url is not None:print('Copy the link:')link = response.xpath('//img[@class="captcha_image"]/@src').extract()[0]print(link)captcha_solution = input('captcha-solution:')captcha_id = parse.parse_qs(parse.urlparse(link).query, True)['id']#继续构造有验证码的formdata结构,将验证码的id和应该输入的值加入进去self.formdata['captcha-solution'] = captcha_solutionself.formdata['captcha-id'] = captcha_id#使用FormRequest进行直接提交访问return [scrapy.FormRequest.from_response(response,formdata=self.formdata,headers=self.headers,meta={'cookiejar': response.meta['cookiejar']},callback=self.after_login,dont_filter=True)]def after_login(self, response):print('判断是否登陆成功。。。。')# 这个位置写上你登录后自己的主页地址,用来判断是不是已经正确登录的test_url = "https://www.douban.com/people/181618569/"if response.url == test_url:if response.status == 200:print('***************')print(u'登录成功')print('***************\n')else:print('***************')print(u'登录失败')print('***************\n')yield scrapy.Request(test_url,meta={'cookiejar': response.meta['cookiejar']},headers=self.headers,callback=self.after_login)#这个里的url就是需要在登录成功后爬取的地址了yield scrapy.Request(url='https://movie.douban.com/subject/26336252/comments?start=0&limit=20&sort=new_score&status=P&percent_type=',meta={'cookiejar': response.meta['cookiejar']},headers=self.headers,callback=self.parse)
#这个是爬取数据结构的方法,就不详细说,都能看懂的,因为没有做分布和代理池,为了防止异步
#瞬时访问次数哦过多导致封IP,在下面我做了一个延时的操作。使用time.sleep()。def parse(self, response):item = DzdItem()next_url = ''if response.status == 200:comments_list = response.css('#comments div[class="comment-item"]')# print(len(comments_list))next_url = response.css('#paginator a[class="next"]::attr(href)').extract_first()for comments in comments_list:user_id = comments.css('::attr(data-cid)').extract_first()comment = comments.css('.comment p span.short::text').extract_first()nick_name = comments.css('span[class = "comment-info"] a::text').extract_first()rating = comments.css('span[class = "comment-info"] span:nth-child(3)::attr(class)').extract_first().replace(' ', '')[7:9]comment_time = comments.css('span[class = "comment-info"] span:nth-child(4)::attr(title)').extract_first()item['user_id'] = user_iditem['comment'] = comment.replace(' ', '')item['nick_name'] = nick_nameitem['rating'] = ratingitem['comment_time'] = comment_timeyield itemif next_url is not None:next_url = 'https://movie.douban.com/subject/26336252/comments' + next_urltime.sleep(random.random() * 3)#因为是带着cookie状态进行访问的,所以不能按照以前的那种直接#request(url,callback=)的方式,需要带上已经从登陆后的cookieyield scrapy.Request(url=next_url,meta={'cookiejar': response.meta['cookiejar']},#也就是说它headers=self.headers,callback=self.parse)else:print('已经没有更多的评论了')print('评论爬取完毕')else:print('Request访问错误,正在尝试重新访问。。。')time.sleep(5)yield scrapy.Request(url=next_url,meta={'cookiejar': response.meta['cookiejar']},headers=self.headers,callback=self.parse)

下面的item.py

import scrapyclass DzdItem(scrapy.Item):
#在这里声明爬取的数据有哪些需要在spider中流转的# define the fields for your item here like:# name = scrapy.Field()user_id = scrapy.Field() #用户idnick_name = scrapy.Field()#用户昵称comment = scrapy.Field()#评论comment_time = scrapy.Field()#评论时间rating = scrapy.Field()#评分

pipelines.py
这部分就是讲数据批量存入数据库中了
在实际运行中,会因为短评的字段过长,导致同一批插入失败导致数据回滚,可以尝试在建表的时候,将comments列的varchar设置大写

import pymysqlclass DzdPipeline(object):comments = []def open_spider(self, spider):self.conn = pymysql.connect(host="localhost", user="root", passwd="Cs123456.", db="movie", charset="utf8")self.cursor = self.conn.cursor()# 批量插入mysql数据库def bulk_insert_to_mysql(self, bulkdata):try:sql = "insert into movie_comments (user_id,nick_name,comment,comment_time,rating) values(%s, %s,%s,%s,%s)"self.cursor.executemany(sql, bulkdata)self.conn.commit()except:print('数据插入有误。。')self.conn.rollback()def process_item(self, item, spider):self.comments.append([item['user_id'], item['nick_name'],item['comment'],item['comment_time'],item['rating']])comments2=[]comments2.append([item['user_id'], item['nick_name'],item['comment'],item['comment_time'],item['rating']])if len(self.comments) == 5:self.bulk_insert_to_mysql(comments2)# 清空缓冲区self.comments.clear()return itemdef close_spider(self, spider):#print( "closing spider,last commit", len(self.comments))self.bulk_insert_to_mysql(self.comments)self.conn.commit()self.cursor.close()self.conn.close()

setting.py文件里,主要一步就是要设置COOKIES_ENABLED = True为True,因为我这里使用了的带着cookie访问的,scrapy默认的事False。如果想用代理池的话,可以在中间件中,如何使用代理池更换IP,百度下你就知道了。

好了,今天的代码就到这里。小伙伴如果有什么疑问或者建议,欢迎评论。我看到了一定会回复的。

我又来了,刚顺手又把数据的词云图和统计图做了

import numpy as np
import pandas as pd
import jieba
import wordcloud
from scipy.misc import imread
import matplotlib.pyplot as plt
from pylab import mpl
import seaborn as sns
from PIL import Image
import pymysqlmpl.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
mpl.rcParams['axes.unicode_minus']def txt_cut(novel, stop_list):return [w for w in jieba.cut(novel) if w not in stop_list and len(w) > 1]def Statistics(txtcut,save_path):# Series是指pandas的一维,获取txtcut中按照降序排列后0~20的数据word_count = pd.Series(txtcut).value_counts().sort_values(ascending=False)[0:20]# print(word_count)# 是以这种形式展现的数据,# 创建一个图形是咧 大小是15*8(长*宽)单位是英寸plt.figure(figsize=(15, 8))x = word_count.index.tolist()  # 获取的是index列,转换成listy = word_count.values.tolist()  # 获取的是values列,转换成list# barplot是作图方法,传入xy值,palette="BuPu_r" 设置的是柱状图的颜色样式# BuPu_r 从左到右,颜色由深到浅,BuPu与之相反sns.barplot(x, y, palette="BuPu_r")plt.title('词频Top20')  # 标题plt.ylabel('count')  # Y轴标题# 如果不加这局,那么出现的就是个四方的框,这个是用来溢出轴脊柱的,加上bottom=tur,意思就是连下方的轴脊柱也溢出sns.despine(bottom=True)# 图片保存plt.savefig(save_path, dpi=400)plt.show()def cloud(result, img_path, cloud_path, cloud_name):result = " ".join(result)  # 必须给个符号分隔开分词结果,否则不能绘制词云# 1、初始化自定义背景图片image = Image.open(img_path)graph = np.array(image)# 2、产生词云图# 有自定义背景图:生成词云图由自定义背景图像素大小决定wc = wordcloud.WordCloud(font_path=r"I:\word-ttf\XingKai.ttf",  # 字体地址background_color='white',  # 背景色max_font_size=100,  # 显示字体最大值max_words=100,  # 最大词数mask=graph)  # 导入的图片wc.generate(result)# 3、绘制文字的颜色以背景图颜色为参考image_color = wordcloud.ImageColorGenerator(graph)  # 从背景图片生成颜色值wc.recolor(color_func=image_color)wc.to_file(cloud_path)  # 按照背景图大小保存绘制好的词云图,比下面程序显示更清晰# 4、显示图片plt.title(cloud_name)  # 指定所绘图名称plt.imshow(wc)  # 以图片的形式显示词云plt.axis("off")  # 关闭图像坐标系plt.show()#链接数据库,获取存入的数据
def open_db():conn = pymysql.connect(host="localhost", user="root", passwd="Cs123456.", db="movie", charset="utf8")cursor = conn.cursor()sql = 'select * from movie_comments'cursor.execute(sql)data = cursor.fetchall()cursor.close()conn.close()return data#对数据处理,获取想要的数据,我这里的list[3]就是查询出的数据获取的
def data_process(data):comment_ob = ''if data is not None:for list in data:comment_ob += list[3] + ','return comment_obdef stop_list(stop_path):stopwords_path = stop_pathstop_list = []stop_list1 = open(stopwords_path, encoding="utf-8").readlines()for line in stop_list1:stop_list.append(line.strip('\n').strip())return stop_listif __name__ == '__main__':#停词地址stop_path = 'I:/鬼吹灯小说分析/stop_word2.txt'stop_list = stop_list(stop_path)#词云背景图地址img_path = "C:/Users/Administrator/Desktop/timg.jpg"#词云图保存地址cloud_path = 'C:/Users/Administrator/Desktop/dzd6_cloud.jpg'#柱状图保存地址stat_path = 'C:/Users/Administrator/Desktop/dzd6_stat.jpg'#词云名称cloud_name = '碟中谍6词云图'data = open_db()ob = data_process(data)jb_comment = txt_cut(ob, stop_list)Statistics(jb_comment,stat_path)cloud(jb_comment, img_path, cloud_path, cloud_name)


好了。这篇文章真的就只到这里了。
咱们下次见。

scrapy框架下的豆瓣电影评论爬取以及登录,以及生成词云和柱状图相关推荐

  1. 豆瓣电影评论爬取+情感分析+词云

    基于b站up主的视频 https://www.bilibili.com/video/BV18C4y1H7mr?t=1444 进行了优化 整合到一个main.py文件中函数式运行 自动化数据清洗 提供了 ...

  2. Colly实现豆瓣电影Top250爬取

    使用 Colly 实现 豆瓣电影Top250爬取 package mainimport ("encoding/csv""github.com/PuerkitoBio/go ...

  3. JAVA爬虫(一):豆瓣电影排行榜爬取

    JAVA爬虫(一):豆瓣电影排行榜爬取 前言 流程图 步骤 一.爬取豆瓣电影榜单网页源代码 二.网页源码解析 三.爬取单个电影网页源码 四.源代码解析及关键信息获取 前言 最近和大创队友一起给大创做的 ...

  4. 豆瓣电影影评爬取---最受欢迎的影评[xpath语法]

    豆瓣电影影评爬取---最受欢迎的影评[xpath语法] 1.基础环境配置: requests-->版本:2.12.4 lxml-->版本:3.7.2 2.爬取网址:https://movi ...

  5. 使用scrapy框架实现,房天下网站全站爬取,详情,动态,评论,户型,图片.

    scrapy  实现代码,代码有点多,没有优化,,下面有链接,不懂得留言 Github全部代码,https://github.com/Agile929/scrapy_fang # -*- coding ...

  6. easyui datalist 不显示数据_爬虫练习——豆瓣电影信息爬取及数据可视化

    最近自学了简单的爬虫项目,简单记录下自己的小白学习路径. 本次爬取的是豆瓣电影TOP250数据,主要用到beautifulsoup.re.urllib库.SQLite包,数据可视化方面主要用到flas ...

  7. 爬虫实战——豆瓣电影短评爬取

    目录 一.任务概述 心路历程 方案制定 二.正式开工 准备工作 处理 json 数据获取电影 id 处理短评 html 源码 三.全部代码 用Access后续处理 一.任务概述 爬取豆瓣电影中2020 ...

  8. python爬取豆瓣电影top250_Python 爬取豆瓣电影Top250排行榜,爬虫初试

    from bs4 import BeautifulSoup import openpyxl import re import urllib.request import urllib.error # ...

  9. python3豆瓣电影排行榜爬取

    项目目标: 爬取豆瓣电影排行榜top250 项目分析: 打开豆瓣电影排行榜网址(以下分别是前三页的网址),由此我们判断只需更改"start=**"的数值既可遍历整个排行榜. htt ...

最新文章

  1. ssh、sftp、scp免密码登录
  2. 算法练习day4——190321(小和、逆序对、划分、荷兰国旗问题)
  3. 如何将FPGA资源平民化?阿里工程师有了新突破
  4. sqli-lab_基础篇_1-23做题反思
  5. 通俗易懂,嵌入式Linux驱动基础
  6. spark-streaming first insight
  7. Hulu CEO预计网站本年营收将达5亿美元
  8. Django09:图书管理系统笔记/choices用法/ MTV与MVC模型/多对多三种创建方式
  9. PHP_APC+Ajax实现的监视进度条的文件上传
  10. PHP通过PHP/JAVA Bridge调用JasperReport报表
  11. 组装电脑时,散热器高度要与机箱适配
  12. Mini-Batch 、Momentum、Adam算法的实现
  13. 监控网站与接口宕机,并推送 App 消息提醒的程序
  14. 微信小程序消息推送至微信公众平台总结
  15. android recyclerView上item的EditextView焦点乱跑和数据混乱
  16. Java HashMap底层实现和原理分析(一)
  17. Web Services Ksoap 下载多张图片
  18. 2020年国内优秀原创IT技术书都在这了
  19. Java周末兼职培训讲师,成功入职阿里
  20. 国外LEAD赚钱的一些习惯

热门文章

  1. 计算机防火墙无法关闭,为什么我电脑的防火墙关不了(win7电脑防火墙怎么关)
  2. 磁力搜索网站+下载神器放送2019-03-05
  3. ffmpeg转换视频内存溢出的问题
  4. Win7系统声卡驱动正常但电脑没声音 扬声器和线路输入“未插入”
  5. 自动化测试之selenium介绍
  6. linux系统使用crontab定时删除日志文件
  7. JAVA的循环结构以及简单操作
  8. 基于大数据技术对基金分析----By Glorio
  9. 快牛智能凉经(数据挖掘日常实习)
  10. 幸福是什么?怎么得到幸福?