爬取《逐梦演艺圈》在豆瓣的长评论,用词云看分数感人的原因。

豆瓣评论爬取

  • 技术使用:python3.6,scrapy,简单的文件操作
  • 爬取的内容是豆瓣中评分感人2.0的《逐梦演艺圈》电影的影评,我本来是只想练习爬虫的,结果看评论看的。。。。哈哈哈哈哈嘎嘎嘎。
  • 转回来

建立工程

  • 在对应的文件夹子中建立工程
  • scrapy startproject douban
  • 然后就会在对应的文件夹子下看到你的douban文件夹。
  • 接下来接着在命令行中,切换到你的工程目录下去,使用命令行创建爬虫
  • scrapy genspider spider douban.com
  • 建议安装一下pycharm,很好用的一款开发IDE。安装方法,出门左转百度,有好多全备的资料
  • 然后打开你创建的工程文件夹
  • 就会看到在这里插入图片描述
  • 是不是有不一样的,其中的mian.txt ,a.txt和start.py是后来创建的,两个文本文档是为了存放数据,应为都是文本数据,就没放到数据库,自己放在文档里看着玩儿,至于start.py是启动工程的文件,都知道可以在命令行里启动,但是现在都用IDE了还跑出去,启动项目,不是很爽,就写个启动项目的
  • start.py的内容很简单
  • from scrapy import cmdline
    cmdline.execute('scrapy crawl spider'.split())
    • 然后打开spiders文件夹下编写spider.py文件
    • 在豆瓣中需要登陆才能获取更多评论信息,所有,先搞一个自动登陆的东西
    • mport scrapy
      from scrapy import Request
      import urllib
      from PIL import Image
      from douban.items import DoubanItem
      class SpiderSpider(scrapy.Spider):
          name = 'spider'
          allowed_domains = ['douban.com']
          start_urls = ['https://accounts.douban.com/login']
          headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
                      AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'}
          item = DoubanItem()
          def start_requests(self):
              url = self.start_urls[0]
              yield Request(url = url,headers=self.headers, callback=self.parse_before_login)
          def parse_before_login(self,response):
              print("登陆前表单填充")
      
              captcha_id = response.xpath('//*[@id="lzform"]/div[6]/div/div/input[2]/@value').extract()
              captcha_image_url = response.xpath('//*[@id="captcha_image"]/@src').extract()
              print(type(captcha_image_url))
              print(captcha_image_url)
              print(captcha_id)
              print(None)
              if captcha_image_url is None:
                  print("登录时无验证码")
                  formdata = {
                      "source":"index_nva",
                      "form_email":"[email protected]",
                      "form_password":"XXXXXXX"
                  }
                  return scrapy.FormRequest.from_response(response, headers=self.headers, formdata=formdata,
                                                          callback=self.parse_after_login)
      
              else:
                  print("登陆时有验证码")
                  save_image_path = 'D:\python_project\douban\captcha.jpeg'
                  urllib.request.urlretrieve(captcha_image_url[0],save_image_path)
                  try:
                      im = Image.open('D:\python_project\douban\captcha.jpeg')
                      im.show()
                  except:
                      pass
                  #手动输入验证码
                  captcha_solution = input('按照打开的图片输入验证码:')
                  formdata = {
                      'source':'None',
                      'redir':'https://www.douban.com',
                      'form_email':'[email protected]',
                      'form_password':'XXXXXXXX',
                      'captcha-solution':captcha_solution,
                      'captcha-id':captcha_id,
                      'login':'登陆'
                  }
                  print('loadding........')
      
                  return scrapy.FormRequest.from_response(response, headers=self.headers, formdata=formdata, callback=self.parse_after_login)
      

      这个就是自动登陆啦。

    • 接下来就是正儿八经的找东西爬取了,豆瓣的评论我看到都是一页一页的,然后每个人的评论都有自己的地址,如果说是直接在把评论区的东西爬取出来,你就会发现,评论一半一半的,超过字数的评论会被隐藏,所以就干脆到各个评论的链接下把评论爬取出来。

    •     def parse_after_login(self,response):
              account = response.xpath('//a[@class="bn-more"]/span/text()').extract_first()
              if account is None:
                  print("登录失败")
              else:
                  print(u"登录成功,当前账户为 %s" % account)
              ids = [i*20 for i in range(0,28)]
              for id in ids:
                  url = 'http://movie.douban.com/subject/26322774/reviews'+'?start={}'.format(id)
                  print(url)
                  yield Request(url=url,headers=self.headers,callback=self.parse,dont_filter=False)
          def parse(self, response):
              print(response.url)
              ids = response.xpath('//*[@id="content"]/div/div[1]/div[1]/div/@data-cid').extract()
              #print(ids)
              for id in ids:
                  url = 'https://movie.douban.com/review/'+id+'/'
                  print(url)
                  yield Request(url=url,headers=self.headers,method="GET",callback=self.parse_page,dont_filter=False)
      
          def parse_page(self,response):
              print(response.url)
              print(response.status)
              comments = response.xpath('//*[@id="link-report"]/div[1]/text()').extract()
              print(comments)

      这就是逐层寻找页面,然后获取评论

    • 运行的话就会打印对应的内容

    • 在运行前我们还需要做些工作,就是数据的保存和代理IP,这种网站是很讨厌别人,丢个虫子过来爬爬爬的,不用代理的话容易被封

    • 我们先搞IP代理,我这里的IP都是免费的,不是很稳定,可以买上一把代理IP来用。

    • 首先来到设置文件

      # Obey robots.txt rules
      ROBOTSTXT_OBEY = False
      
      # Configure maximum concurrent requests performed by Scrapy (default: 16)
      #CONCURRENT_REQUESTS = 32
      
      # Configure a delay for requests for the same website (default: 0)
      # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay
      # See also autothrottle settings and docs
      DOWNLOAD_DELAY = 10
      
      IPPOOL=[
      	{"ipaddr":"61.135.217.7:80"},
      	{"ipaddr":"114.253.36.180:9999"},
      	{"ipaddr":"125.70.13.77:8080"},
      	{"ipaddr":"121.49.110.65:8888"},
      	{"ipaddr":"106.75.226.36:808"},
      	{"ipaddr":"118.190.95.35:9001"},
      	{"ipaddr":"180.163.152.130:60596"},
      	{"ipaddr":"175.175.218.48:1133"},
      	{"ipaddr":"115.46.65.209:8123"},
      	{"ipaddr":"182.88.88.110:8123"},
      	{"ipaddr":"171.38.34.80:8123"},
      	{"ipaddr":"175.165.128.228:1133"},
      	{"ipaddr":"175.148.72.52:1133"},
      	{"ipaddr":"115.46.78.31:8123"},
      	{"ipaddr":"123.180.68.168:8010"},
      	{"ipaddr":"121.228.48.32:3128"},
      	{"ipaddr":"171.37.154.105:8123"},
      	{"ipaddr":"114.230.41.230:3128"},
      	{"ipaddr":"221.232.233.200:8010"},
      	{"ipaddr":"221.229.18.142:808"}
      ]
      DOWNLOADER_MIDDLEWARES = {
          'douban.middlewares.DoubanDownloaderMiddleware': 543,
          'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware':543,
          'douban.middlewares.MyProxiesSpiderMiddleware':125
      }

      这是对IP代理在settings.py文件中的一些设置,其中的ROBOTSTXT_OBEY和DOWNLOAD_DELA的设置是为了多些虫子被从页面中丢出来的事故,这里的爬取频率,个人建议不要低于4。

    • 然后根据框架,我们在middlewares.py文件中开启代理

    • 先导入头

    • import random
      from douban.settings import IPPOOL

      这里的random是为了实现随机代理

    • class MyProxiesSpiderMiddleware(object):
         def __init__(self,ip=''):
             self.ip = ip
         def process_request(self,request,spider):
             thisip = random.choice(IPPOOL)
             print('this is ip:'+thisip['ipaddr'])
             request.meta['proxy']='http://'+thisip['ipaddr']

      设置好你的代理IP之后,网页就找不到你的IP,最后你的代理不够靠普,让你访问不到信息。

    • 然后数据放到txt这是最白甜的数据存放方式了。

    • 打开piplines.py

    • import os
      import codecs
      
      class DoubanPipeline(object):
          def __init__(self):
              self.file = codecs.open('mian.txt','a',encoding='utf-8')
          def process_item(self, item, spider):
              # 获取当前工作目录
              self.file.write(item['comment'])
              print('数据写入')
              return item
          def spider_closed(self):
              self.file.close()
      

      文件的话路径要是不确定的话,就写绝对路径

    • 在settings.py中设置开启我们的piplines

    • ITEM_PIPELINES = {
          'douban.pipelines.DoubanPipeline': 300,
      }

      这就完事儿了,接下里就是放着它跑吧

    • IP代理因为免费的,我的就不是很稳。。。。。。难受。。,,穷限制了我的虫子

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------接下来我们把数据进行处理,看看,这个片儿为啥烂。

  • 我们利用词云把数据进行统计,使用词云是应为,我最进刚学了,所以就用用,没啥别的原因。
  • 使用词云需要一个模块就是wordCloud的模块,没有的需要pip一下子
  • 应为就是直接对模块的使用,就直接上代码了。出门有很多的大牛写的好的,大家可以拿来尝尝。
  • 代码
  •  
  • import jieba.analyse
    from PIL import Image, ImageSequence
    import numpy as np
    import matplotlib.pyplot as plt
    from wordcloud import WordCloud, ImageColorGenerator
    
    l = ''
    f = open('a.txt', 'r') #这个就是你的数据源,打开数据时和数据进行截取可以使用结巴分词器
    for i in f:
        l += f.read()
    
    result = jieba.analyse.textrank(l, topK=250, withWeight=True) 
    keyworlds = dict()
    for i in result:
        keyworlds[i[0]] = i[1]
    
    # print(keyworlds)
    
    image = Image.open('timg.jpg') #这个就是你的背景,想要好看的,背景图颜色多一点
    graph = np.array(image)
    wc = WordCloud(font_path='simhei.ttf', background_color='White', max_font_size=170, mask=graph)
    wc.generate_from_frequencies(keyworlds)
    image_color = ImageColorGenerator(graph)
    plt.imshow(wc)
    plt.imshow(wc.recolor(color_func=image_color))
    plt.axis('off')
    plt.show()
    wc.to_file('1.png')
    

    这就是全部的代码,也就几行

  • 效果图

从图上你可以看到出现次数,也就是出现频率最高的词汇,就是~~~~~啥啥。

发布了23 篇原创文章 · 获赞 22 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36389249/article/details/83340095