zoukankan      html  css  js  c++  java
  • 作业——08 爬虫综合大作业

    作业的要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3075


     一.把爬取的内容保存取MySQL数据库

    • import pandas as pd
    • import pymysql
    • from sqlalchemy import create_engine
    • conInfo = "mysql+pymysql://user:passwd@host:port/gzccnews?charset=utf8"
    • engine = create_engine(conInfo,encoding='utf-8')
    • df = pd.DataFrame(allnews)
    • df.to_sql(name = ‘news', con = engine, if_exists = 'append', index = False)
    import pandas as pd
    import requests
    from bs4 import BeautifulSoup
    from datetime import datetime
    import re
    import time
    import random
    import sqlite3 
    
    import pymysql
    from sqlalchemy import create_engine
    coninfo='mysql+pymysql://root:lyh0523@localhost:3306/gzccnews?charset=utf8'
    engine = create_engine(coninfo,encoding='utf-8')
    
    def click(url):
        id = re.findall('(d{1,5})',url)[-1]#返回所有匹配的字符串的字符串列表的最后一个
        clickUrl = 'http://oa.gzcc.cn/api.php?op=count&id={}&modelid=80'.format(id)
        resClick = requests.get(clickUrl)
        newsClick = int(resClick.text.split('.html')[-1].lstrip("('").rstrip("');"))
        return newsClick
    #时间
    def newsdt(showinfo):
        newsDate = showinfo.split()[0].split(':')[1]
        newsTime = showinfo.split()[1]
        newsDT = newsDate+' '+newsTime
        dt = datetime.strptime(newsDT,'%Y-%m-%d %H:%M:%S')#转换成datetime类型
        return dt
    #内容
    def anews(url):
        newsDetail = {}
        res = requests.get(url)
        res.encoding = 'utf-8'
        soup = BeautifulSoup(res.text,'html.parser')
        newsDetail['newsTitle'] = soup.select('.show-title')[0].text#题目
        showinfo = soup.select('.show-info')[0].text
        newsDetail['newsDT'] = newsdt(showinfo)#时间
        newsDetail['newsClick'] = click(url)#点击次数
        return newsDetail
    
    def alist(url):
        res = requests.get(listUrl)
        res.encoding = 'utf-8'
        soup = BeautifulSoup(res.text, 'html.parser')
        newsList = []
        for news in soup.select('li'):#获取li元素
            if len(news.select('.news-list-title'))>0:#如果存在新闻题目
                newsUrl = news.select('a')[0]['href']#获取新闻的链接
                newsDesc = news.select('.news-list-description')[0].text#获取摘要文本
                newsDict = anews(newsUrl)#通过链接获取题目时间点击数
                newsDict['description'] = newsDesc
                newsList.append(newsDict)#把每个新闻的信息放进字典扩展到列表里
        return newsList
    
    allnews = []
    for i in range(59,69):
        listUrl = 'http://news.gzcc.cn/html/xiaoyuanxinwen/{}.html'.format(i)
        allnews.extend(alist(listUrl))
    
    pd.Series(anews)
    newsdf=pd.DataFrame(allnews)
    for i in range(5):
        print(i)
        time.sleep(random.random()*3)        
        print(newsdf)
        
            
    newsdf.to_csv('123.csv')   #在本地项目下生成一个表格存储爬取新闻内容
    
    newsdf.to_sql(name='news',con=engine,if_exists='append',index=False)
    conn=pymysql.connect(host='localhost',port=3306,user='root',passwd='lyh0523',db='gzccnews',charset='utf8')
    
    with sqlite3.connect('gzccnewsdb.sqlite') as db:
         newsdf.to_sql('gzccnewsdb',db)    #在本地项目下生成一个数据库存储爬取新闻内容
    完整代码

    效果图:

    二.爬虫综合大作业

    1. 选择一个热点或者你感兴趣的主题。
    2. 选择爬取的对象与范围。
    3. 了解爬取对象的限制与约束。
    4. 爬取相应内容。
    5. 做数据分析与文本分析。
    6. 形成一篇文章,有说明、技术要点、有数据、有数据分析图形化展示与说明、文本分析图形化展示与说明。
    7. 文章公开发布。

    正文分割线


       

      对于经常逛B站的动漫迷来说,弹幕是最值得研究的一个部分,我们可以通过弹幕来判断该短视频的受欢迎程度。故在此借助爬虫技术对一个视频的弹幕进行爬取,观察观众的关注点。最近的漫威上映了一部新电影——复仇者联盟:终局之战,吸引了无数的漫威粉前去观看,对于漫威一直以来的那么多部与之相关的电影,不少人都想重温之前发生的事情,故有up主把复仇者联盟从无到有,从古到今的所有时间线,都整理出来了。本文就是对该up主的视频进行解析。

    导包:

      import requests-----网页请求

      import time-----延时操作

      import jieba----分词操作

      import numpy as np-----图片格式转换为数组 from PIL

      import Image-----图片的读取 from wordcloud

      import WordCloud as wc----词云制作

    网页分析:

      https://www.bilibili.com/video/av49842011这是目标资源,通过开发者工具找到弹幕的链接(别问我怎么知道的),在此可以看到目标资源的所有弹幕信息

      list.so?oid=xxxx的结果,这就是我们要找的弹幕资源。

      因此,我所要寻找的id不是平时网页地址栏的id,而是被隐藏了的id。

    网页获取和解析:

      把对网页的所有操作封装在一个类里面。初始化是设置请求头和url以及弹幕的获取,在此把整个xml文件下载到本地,用xpath解析xml文档。

    def __init__(self,oid):
            self.headers={
            'Host': 'api.bilibili.com',
            'Connection': 'keep-alive',
            'Cache-Control': 'max-age=0',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Cookie': 'finger=edc6ecda; LIVE_BUVID=AUTO1415378023816310; stardustvideo=1; CURRENT_FNVAL=8; buvid3=0D8F3D74-987D-442D-99CF-42BC9A967709149017infoc; rpdid=olwimklsiidoskmqwipww; fts=1537803390'
    
            }
            self.url='https://api.bilibili.com/x/v1/dm/list.so?oid='+str(oid)
            self.barrage_reault=self.get_page()
    
        # 获取信息
        def get_page(self):
            try:
                # 延时操作,防止太快爬取
                time.sleep(0.5)
                response=requests.get(self.url,headers=self.headers)
            except Exception as e:
                print('获取xml内容失败,%s' % e)
                return False
            else:
                if response.status_code == 200:
                    # 下载xml文件
                    with open('bilibilidanmu.xml','wb') as f:
                        f.write(response.content)
                    return True
                else:
                    return False
    
        # 解析网页
        def param_page(self):
            time.sleep(1)
            if  self.barrage_reault:
                # 文件路径,html解析器
                html=etree.parse('bilibilidanmu.xml',etree.HTMLParser())
                # xpath解析,获取当前所有的d标签下的所有文本内容
                results=html.xpath('//d//text()')
                return results
    解析网页

    弹幕去重:

      把弹幕内容存储到一个空的列表(result)中,每次准备存入一条弹幕都判断该列表是否已经含有该元素,有的话就添加到double_barrage列表和barrage集合中,方面接下来对重复的弹幕内容的统计。

    # 弹幕去重
        def remove_double_barrage(self):
            '''
            double_arrage:所有重复弹幕的集合
            results:去重后的弹幕
            barrage:每种弹幕内容都存储一遍
            '''
            double_barrage=[]
            results=[]
            barrage=set()
            for result in self.param_page():
                if result not in results:
                    results.append(result)
                else:
                    double_barrage.append(result)
                    barrage.add(result)
            return double_barrage,results,barrage
    弹幕去重

    弹幕重复内容的计数和词云的制作:

      此处利用np.array(Image)函数,对生成的词云的图片大小进行限定。

    # 弹幕重复计算和词云的制作
        def make_wordCould(self):
            double_barrages,results,barrages=self.remove_double_barrage()
            # 重词计数
            with open('barrages.csv','w',encoding='utf8') as f:
                for barrage in barrages:
                    amount=double_barrages.count(barrage)
                    f.write(barrage+':'+str(amount+1)+'
    ')
                    
            # 设置停用词
            stop_words=['','',',','.','?','!','']
            words=[]
            if results:
                for result in results:
                    for stop in stop_words:
                        result=''.join(result.split(stop))
                    words.append(result)
                # 列表拼接成字符串
                words=''.join(words)
                words=jieba.cut(words)
                words=''.join(words)
                wcloud=np.array(Image.open('pic.jpg'))#wordcloud的形状=(初始图片的宽度、高度、通道)
                w=wc(font_path='‪C:/Windows/Fonts/SIMYOU.TTF',background_color='white',width=1600,height=1600,max_words=2000,mask=wcloud)
                w.generate(words)
                w.to_file('wcloud.jpg')
    生成词云

    实现的效果:

      从词云中可以看出一下几点:

      • 对up主做出来的视频的认可,对其说一句“辛苦了”;
      • 钢铁侠“妮妮”和奇异博士“本尼”这两位英雄比较受欢迎;
      • 对视频展现的方式感到滑稽的也有不少观众。

       当然,这个项目爬取的弹幕信息只是截止到该文章发表的时间,同一个视频在不同的时间爬取的弹幕所生成的词云会有所不同,期待过一两天这个视频所生成的词云会变成什么样。

      在这个项目中还有不足的地方有以下几点:

      • 可以对弹幕发布时间的分析;
      • 对多个时间段的弹幕进行对比分析。

      最后,在此奉上完整的代码~

    from lxml import etree
    import  requests
    import time
    import jieba
    import numpy as np
    from PIL import Image
    from wordcloud import WordCloud as wc
    class Bilibili():
        """docstring for Bilibili"""
        def __init__(self,oid):
            self.headers={
            'Host': 'api.bilibili.com',
            'Connection': 'keep-alive',
            'Cache-Control': 'max-age=0',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Encoding': 'gzip, deflate, br',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Cookie': 'finger=edc6ecda; LIVE_BUVID=AUTO1415378023816310; stardustvideo=1; CURRENT_FNVAL=8; buvid3=0D8F3D74-987D-442D-99CF-42BC9A967709149017infoc; rpdid=olwimklsiidoskmqwipww; fts=1537803390'
    
            }
            self.url='https://api.bilibili.com/x/v1/dm/list.so?oid='+str(oid)
            self.barrage_reault=self.get_page()
    
        # 获取信息
        def get_page(self):
            try:
                # 延时操作,防止太快爬取
                time.sleep(0.5)
                response=requests.get(self.url,headers=self.headers)
            except Exception as e:
                print('获取xml内容失败,%s' % e)
                return False
            else:
                if response.status_code == 200:
                    # 下载xml文件
                    with open('bilibilidanmu.xml','wb') as f:
                        f.write(response.content)
                    return True
                else:
                    return False
    
        # 解析网页
        def param_page(self):
            time.sleep(1)
            if  self.barrage_reault:
                # 文件路径,html解析器
                html=etree.parse('bilibilidanmu.xml',etree.HTMLParser())
                # xpath解析,获取当前所有的d标签下的所有文本内容
                results=html.xpath('//d//text()')
                return results
    
        # 弹幕去重
        def remove_double_barrage(self):
            '''
            double_arrage:所有重复弹幕的集合
            results:去重后的弹幕
            barrage:每种弹幕内容都存储一遍
            '''
            double_barrage=[]
            results=[]
            barrage=set()
            for result in self.param_page():
                if result not in results:
                    results.append(result)
                else:
                    double_barrage.append(result)
                    barrage.add(result)
            return double_barrage,results,barrage
    
        # 弹幕重复计算和词云的制作
        def make_wordCould(self):
            double_barrages,results,barrages=self.remove_double_barrage()
            # 重词计数
            with open('barrages.csv','w',encoding='utf8') as f:
                for barrage in barrages:
                    amount=double_barrages.count(barrage)
                    f.write(barrage+':'+str(amount+1)+'
    ')
                    
            # 设置停用词
            stop_words=['','',',','.','?','!','']
            words=[]
            if results:
                for result in results:
                    for stop in stop_words:
                        result=''.join(result.split(stop))
                    words.append(result)
                # 列表拼接成字符串
                words=''.join(words)
                words=jieba.cut(words)
                words=''.join(words)
                wcloud=np.array(Image.open('pic.jpg'))#wordcloud的形状=(初始图片的宽度、高度、通道)
                w=wc(font_path='‪C:/Windows/Fonts/SIMYOU.TTF',background_color='white',width=1600,height=1600,max_words=2000,mask=wcloud)
                w.generate(words)
                w.to_file('wcloud.jpg')
                
    
    b=Bilibili(87335045)#弹幕资源 f12-->netword-->all-->list.so?oid=XXXX
    #b=Bilibili(2238927)
    b.make_wordCould()
    完整代码
  • 相关阅读:
    手把手教你写vue插件并发布(一)
    npm 换源
    ajax上传文件显示进度
    angularjs的表单验证
    利用公钥认证登录远程服务器
    centos 搭建 leanote
    读书笔记-JavaScript高级程序设计(1)
    C++读写TXT文件中的string或者int型数据以及string流的用法
    不相交集ADT--链表实现
    不相交集ADT--数组实现
  • 原文地址:https://www.cnblogs.com/linxiLYH/p/10760453.html
Copyright © 2011-2022 走看看