一个完整的大作业

获取中国航空器拥有者及驾驶员协会(Aircraft Owners and Pilots Association of China)的所有协会动态信息

 

 要求

选一个自己感兴趣的主题。

网络上爬取相关的数据。

进行文本分析,生成词云。

对文本分析结果解释说明。

写一篇完整的博客,附上源代码、数据爬取及分析结果,形成一个可展示的成果。

 

 

1、首先使用谷歌浏览器打开中国航空器拥有者及驾驶员协会协会动态的网页http://www.aopa.org.cn/news/list.php?catid=8,在空白地方点击鼠标右键调出开发者工具或者使用快捷键F12。

 

 

2、通过查看其中一条标题的代码,可以看出每条消息的标题、链接、及其发布时间。

 

 

3、测试获取标题、标题链接、及发布时间代码

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re

aopaurl='http://www.aopa.org.cn/news/list.php?catid=8'
res=requests.get(aopaurl)
res.encoding='utf-8'
soup =BeautifulSoup(res.text,'html.parser')
for news in soup.select('.catlist'):
    time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容  
    title=news.select('a')[0]['title']#标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
    url=news.select('a')[0]['href']#链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
    dt=datetime.strptime(time,'%Y-%m-%d %H:%M')#将其中的时间str转换成datetime类型
    print( "时间:",dt,"\t标题:",title,"\t链接:",url)

 

 

4、获取第一页标题链接、标题、发布时间

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re

aopaurl='http://www.aopa.org.cn/news/list.php?catid=8'
res=requests.get(aopaurl)
res.encoding='utf-8'
soup =BeautifulSoup(res.text,'html.parser')
for news in soup.select('.catlist'):
    for news2 in news.select('.catlist_li'):
        if len((news2))>0:
            time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容  
            title=news.select('a')[0]['title']#标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
            url=news.select('a')[0]['href']#链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
            dt=datetime.strptime(time,'%Y-%m-%d %H:%M')#将其中的时间str转换成datetime类型
            print( "时间:",dt,"\t标题:",title,"\t链接:",url)

 

 

5、打开其中一个标题http://www.aopa.org.cn/news/show-17824.html,通过观察得知消息详情在content

 

 

 

6、取其中一条信息详情

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re
aopaurl='http://www.aopa.org.cn/news/show-17824.html'
res=requests.get(aopaurl)
res.encoding='utf-8'
soupn =BeautifulSoup(res.text,'html.parser')
detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
print(detail)

 

 

 7、把获取详情代码封装成函数

def getdetail(url):#将取得详细内容的代码包装成函数
    resn=requests.get(url)
    resn.encoding='utf-8'
    soupn=BeautifulSoup(resn.text,'html.parser')
    detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
    return (detail)

 

 

8、把获取第一页的代码封装为函数并且结构化数据

def getdetail(eachpageurl):#将取得详细内容的代码包装成函数
    resn=requests.get(eachpageurl)
    resn.encoding='utf-8'
    soupn=BeautifulSoup(resn.text,'html.parser')
    detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
    return (detail)

def getonenews(news):#将获取单条新闻的代码封装成函数
    onenews = {} #单条新闻字典
    time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容
    onenews['title']=news.select('a')[0]['title'] #标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
    onenews['url']=news.select('a')[0]['href'] #链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
    onenews['dt']=datetime.strptime(time,'%Y-%m-%d %H:%M') #将其中的时间str转换成datetime类型
    onenews['detail']=getdetail(news.select('a')[0]['href'])
    return(onenews)

def getnews(pageurl): #将取得单页内容的代码包装成函数
    res=requests.get(pageurl)
    res.encoding='utf-8'
    soup =BeautifulSoup(res.text,'html.parser') 
    newsls=[] #单页新闻list列表
    for news in soup.select('.catlist'):
        for news2 in news.select('.catlist_li'):
            if len(news2)>0:
                newsls.append(getonenews(news2)) #把单条新闻字典加入列表
    return(newsls)

 

 

9、通过观察获知该网站的第一页与之后的每一页的网址末尾略有区别,编写代码时要首页需要注意单独输出。

 

 

10、构造第二页到尾页的网址

for i in range(2,44):
    listurl=('http://www.aopa.org.cn/news/list-8-{}.html'.format(i))
    print(listurl)

 

 

11、拼合以上内容测试,发现输出到标题为“飞行大会今日迎首批飞来者——山河通航侯珉带队驾机飞抵旧州机场”时报错,是因为下一条信息的网页并不规范。

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re
import pandas
import sqlite3

def checkurl(url):
    #http://www.aopa.org.cn
    urlexm='www.aopa.org'
    j=0
    if len(url)>13:
        urlch=url[7:19]
        if urlch==urlexm:
            j=1
        else:
            j=0
    else:
        j=0
    return(j,urlch)

def getdetail(eachpageurl):#将取得详细内容的代码包装成函数
    resn=requests.get(eachpageurl)
    resn.encoding='utf-8'
    soupn=BeautifulSoup(resn.text,'html.parser')
    detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
    return (detail)

def getonenews(news):#将获取单条新闻的代码封装成函数
    onenews = {} #单条新闻字典
    time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容
    onenews['title']=news.select('a')[0]['title'] #标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
    onenews['url']=news.select('a')[0]['href'] #链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
    onenews['dt']=datetime.strptime(time,'%Y-%m-%d %H:%M') #将其中的时间str转换成datetime类型
    onenews['detail']=getdetail(news.select('a')[0]['href'])
    return(onenews)

def getnews(pageurl): #将取得单页内容的代码包装成函数
    res=requests.get(pageurl)
    res.encoding='utf-8'
    soup =BeautifulSoup(res.text,'html.parser') 
    newsls=[] #单页新闻list列表
    for news in soup.select('.catlist'):
        for news2 in news.select('.catlist_li'):
            if len(news2)>0:
                newsls.append(getonenews(news2)) #把单条新闻字典加入列表
    return(newsls)
print(getnews('http://www.aopa.org.cn/news/list.php?catid=8'))

newstotal=[]
aopaurl='http://www.aopa.org.cn/news/list.php?catid=8'
newstotal.append(getnews(aopaurl)) #获取首页内容

for i in range(2,3):
    listurl=('http://www.aopa.org.cn/news/list-8-{}.html'.format(i))
    newstotal.append(getnews(listurl))

print(newstotal)

 

 

 

12、避免上一步的网页错误添加一个判断步骤

def checkurl(url):
    #http://www.aopa.org.cn
    urlexm='www.aopa.org'
    j=0
    if len(url)>13:
        urlch=url[7:19]
        if urlch==urlexm:
            j=1
        else:
            j=0
    else:
        j=0
    return(j)

 

 

13、重新整合代码,由于信息量太大,这里输出newstotal的长度,显示结果为42页。

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re
import pandas
import sqlite3

def checkurl(url):
    #http://www.aopa.org.cn
    urlexm='www.aopa.org'
    j=0
    if len(url)>13:
        urlch=url[7:19]
        if urlch==urlexm:
            j=1
        else:
            j=0
    else:
        j=0
    return(j)

def getdetail(eachpageurl):#将取得详细内容的代码包装成函数
    resn=requests.get(eachpageurl)
    resn.encoding='utf-8'
    soupn=BeautifulSoup(resn.text,'html.parser')
    detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
    return (detail)

def getonenews(news):#将获取单条新闻的代码封装成函数
    onenews = {} #单条新闻字典
    time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容
    onenews['title']=news.select('a')[0]['title'] #标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
    onenews['url']=news.select('a')[0]['href'] #链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
    onenews['dt']=datetime.strptime(time,'%Y-%m-%d %H:%M') #将其中的时间str转换成datetime类型

    i=checkurl(news.select('a')[0]['href']) #检查详情的网址是否符合规范
    if i==1:
        onenews['detail']=getdetail(news.select('a')[0]['href'])
    else:
        onenews['detail']='该网页不规范'
    return(onenews)

def getnews(pageurl): #将取得单页内容的代码包装成函数
    res=requests.get(pageurl)
    res.encoding='utf-8'
    soup =BeautifulSoup(res.text,'html.parser') 
    newsls=[] #单页新闻list列表
    for news in soup.select('.catlist'):
        for news2 in news.select('.catlist_li'):
            if len(news2)>0:
                newsls.append(getonenews(news2)) #把单条新闻字典加入列表
                #break
    return(newsls)
#print(getnews('http://www.aopa.org.cn/news/list.php?catid=8'))

newstotal=[]
aopaurl='http://www.aopa.org.cn/news/list.php?catid=8'
newstotal.extend(getnews(aopaurl)) #获取首页内容

for i in range(2,3):
    listurl=('http://www.aopa.org.cn/news/list-8-{}.html'.format(i))
    newstotal.extend(getnews(listurl))

print(newstotal)

 

 

 

14、把获取到的新闻列表输出到exl以及数据库

df = pandas.DataFrame(newstotal)
#print(df.head())
#print(df['title'])

df.to_excel('AOPAnews.xlsx')

with sqlite3.connect('AOPAnewsdb.sqlite') as db:
    df.to_sql('AOPAnewsdb',con=db)

 

 

15、接着制作词云部分,需要添加以下几个包。

import jieba
from wordcloud import WordCloud
import matplotlib.pyplot as plt

 

 

16、整合多条新闻的详情并调整格式。

def detailwc(totallist): #把多条detail合并
    detailall=''
    for a in range(len(totallist)):
        detailall += newstotal[a]['detail'] + "\n"
    detailall=detailall.replace("\n",'') #去掉回车
    detailall=detailall.replace(" ",'')
    return(detailall)

 

 

17、测试制作词云的词群。

def showordcloud(lsall): #制作词云

    words = jieba.lcut(lsall) #结巴分词
    counts = {}
    for w in words: #统计词语出现次数
        if len(w) ==1:
            continue
        else:
            counts[w] = counts.get(w,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)

    wcls20=''
    for i in range(20): #制作词群
        for j in range(items[i][1]):
            wcls20 +=' '+items[i][0]
    wl_split=''.join(wcls20)
    #print(wl_split)
    
    mywc = WordCloud().generate(wl_split) #文本词频统计函数,本函数自动统计词的个数,以字典形式内部存储,在显示的时候词频大的,字体也大
    plt.imshow(mywc)
    plt.axis("off")
    plt.show()

 

 

18、完整制作词云代码,成功绘制出词云。

def showordcloud(lsall): #制作词云

    words = jieba.lcut(lsall)
    counts = {}
    for w in words: #统计词语出现次数
        if len(w) ==1:
            continue
        else:
            counts[w] = counts.get(w,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)

    wcls20=''
    for i in range(20):
        for j in range(items[i][1]):
            wcls20 +=' '+items[i][0]
    wl_split=''.join(wcls20)
    #print(wl_split)
    
    mywc = WordCloud().generate(wl_split) #文本词频统计函数,本函数自动统计词的个数,以字典形式内部存储,在显示的时候词频大的,字体也大
    plt.imshow(mywc)
    plt.axis("off")
    plt.show()

 

19、结合上面的函数测试。

 

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re
import pandas
import sqlite3
import jieba
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import numpy as np

def showordcloud(lsall): #制作词云

    words = jieba.lcut(lsall) #结巴分词
    counts = {}
    for w in words: #统计词语出现次数
        if len(w) ==1:
            continue
        else:
            counts[w] = counts.get(w,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)

    wcls20=''
    for i in range(20): #制作词群
        for j in range(items[i][1]):
            wcls20 +=' '+items[i][0]
    wl_split=''.join(wcls20)
    #print(wl_split)
    
    mywc = WordCloud().generate(wl_split) #文本词频统计函数,本函数自动统计词的个数,以字典形式内部存储,在显示的时候词频大的,字体也大
    plt.imshow(mywc)
    plt.axis("off")
    plt.show()
    

def detailwc(totallist): #把多条detail合并
    detailall=''
    for a in range(len(totallist)):
        detailall += newstotal[a]['detail'] + "\n"
    detailall=detailall.replace("\n",'') #去掉回车
    detailall=detailall.replace(" ",'')
    return(detailall)

def checkurl(url):
    #http://www.aopa.org.cn
    urlexm='www.aopa.org'
    j=0
    if len(url)>13:
        urlch=url[7:19]
        if urlch==urlexm:
            j=1
        else:
            j=0
    else:
        j=0
    return(j)

def getdetail(eachpageurl):#将取得详细内容的代码包装成函数
    resn=requests.get(eachpageurl)
    resn.encoding='utf-8'
    soupn=BeautifulSoup(resn.text,'html.parser')
    detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
    return (detail)

def getonenews(news):#将获取单条新闻的代码封装成函数
    onenews = {} #单条新闻字典
    time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容
    onenews['title']=news.select('a')[0]['title'] #标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
    onenews['url']=news.select('a')[0]['href'] #链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
    onenews['dt']=datetime.strptime(time,'%Y-%m-%d %H:%M') #将其中的时间str转换成datetime类型

    i=checkurl(news.select('a')[0]['href']) #检查详情的网址是否符合规范
    if i==1:
        onenews['detail']=getdetail(news.select('a')[0]['href'])
    else:
        onenews['detail']='该网页不规范'
    return(onenews)

def getnews(pageurl): #将取得单页内容的代码包装成函数
    res=requests.get(pageurl)
    res.encoding='utf-8'
    soup =BeautifulSoup(res.text,'html.parser') 
    newsls=[] #单页新闻list列表
    for news in soup.select('.catlist'):
        for news2 in news.select('.catlist_li'):
            if len(news2)>0:
                newsls.append(getonenews(news2)) #把单条新闻字典加入列表
                #break
    return(newsls)
#print(getnews('http://www.aopa.org.cn/news/list-8.html'))


newstotal=[] #所有新闻列表
aopaurl='http://www.aopa.org.cn/news/list.php?catid=8'
newstotal.extend(getnews(aopaurl)) #获取首页全部内容并加入所有新闻列表

for i in range(2,3):#构造首页以外的网址,获取首页之后全部内容并加入所有新闻列表
    listurl=('http://www.aopa.org.cn/news/list-8-{}.html'.format(i))
    newstotal.extend(getnews(listurl))

#print(len(newstotal))

#print(detailwc(newstotal))
showordcloud(detailwc(newstotal))

df = pandas.DataFrame(newstotal)
#print(df.head())
#print(df['detail'])

df.to_excel('AOPAnews.xlsx')

with sqlite3.connect('AOPAnewsdb.sqlite') as db:
    df.to_sql('AOPAnewsdb',con=db)

 

20、把词云更改成自己喜欢的图案,需要新增以下几个包。

from wordcloud import WordCloud,ImageColorGenerator
import os
from scipy.misc import imread

 

 21、制作词云的函数也需要改动

def showordcloud(lsall): #制作词云
    os.chdir('C:/Users/Administrator/Desktop/S.H.I.E.L.D/Python') #改变当前路径
    hzw= imread('hzw.png')
    words = jieba.lcut(lsall) #结巴分词
    counts = {}
    for w in words: #统计词语出现次数
        if len(w) ==1:
            continue
        else:
            counts[w] = counts.get(w,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)

    wcls20=''
    for i in range(20): #制作词群
        for j in range(items[i][1]):
            wcls20 +=' '+items[i][0]
    wl_split=''.join(wcls20)
    #print(wl_split)
    
    mywc = WordCloud(background_color="white",margin=5, width=1500, height=1500,mask=hzw).generate(wl_split) #文本词频统计函数,本函数自动统计词的个数,以字典形式内部存储,在显示的时候词频大的,字体也大
    image_colors = ImageColorGenerator(hzw) #从背景图片生成颜色值
    plt.imshow(mywc)
    plt.axis("off")
    plt.show()
    mywc.to_file('WC.png') 

 

 22、最终代码及输出词云

 

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re
import pandas
import sqlite3
import jieba
from wordcloud import WordCloud,ImageColorGenerator
import matplotlib.pyplot as plt
import numpy as np
import os
from scipy.misc import imread

def showordcloud(lsall): #制作词云
    os.chdir('C:/Users/Administrator/Desktop/S.H.I.E.L.D/Python') #改变当前路径
    hzw= imread('hzw.png')
    words = jieba.lcut(lsall) #结巴分词
    counts = {}
    for w in words: #统计词语出现次数
        if len(w) ==1:
            continue
        else:
            counts[w] = counts.get(w,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)

    wcls20=''
    for i in range(20): #制作词群
        for j in range(items[i][1]):
            wcls20 +=' '+items[i][0]
    wl_split=''.join(wcls20)
    #print(wl_split)
    
    mywc = WordCloud(background_color="white",margin=5, width=1500, height=1500,mask=hzw).generate(wl_split) #文本词频统计函数,本函数自动统计词的个数,以字典形式内部存储,在显示的时候词频大的,字体也大
    image_colors = ImageColorGenerator(hzw) #从背景图片生成颜色值
    plt.imshow(mywc)
    plt.axis("off")
    plt.show()
    mywc.to_file('WC.png')
    

def detailwc(totallist): #把多条detail合并
    detailall=''
    for a in range(len(totallist)):
        detailall += newstotal[a]['detail'] + "\n"
    detailall=detailall.replace("\n",'') #去掉回车
    detailall=detailall.replace(" ",'')
    return(detailall)

def checkurl(url):
    #http://www.aopa.org.cn
    urlexm='www.aopa.org'
    j=0
    if len(url)>13:
        urlch=url[7:19]
        if urlch==urlexm:
            j=1
        else:
            j=0
    else:
        j=0
    return(j)

def getdetail(eachpageurl):#将取得详细内容的代码包装成函数
    resn=requests.get(eachpageurl)
    resn.encoding='utf-8'
    soupn=BeautifulSoup(resn.text,'html.parser')
    detail=soupn.select('.content')[0].text #详情,选取包含content的class,提取取出list列表第一个元素,选取当中的非代码文本内容
    return (detail)

def getonenews(news):#将获取单条新闻的代码封装成函数
    onenews = {} #单条新闻字典
    time=news.select('span')[0].text #时间,选取<span>的全部内容,取出list列表第一个元素,选取当中的非代码文本内容
    onenews['title']=news.select('a')[0]['title'] #标题,选取<a>的全部内容,取出list列表第一个元素,选取当中title文本
    onenews['url']=news.select('a')[0]['href'] #链接,选取<a>的全部内容,取出list列表第一个元素,选取当中href文本
    onenews['dt']=datetime.strptime(time,'%Y-%m-%d %H:%M') #将其中的时间str转换成datetime类型

    i=checkurl(news.select('a')[0]['href']) #检查详情的网址是否符合规范
    if i==1:
        onenews['detail']=getdetail(news.select('a')[0]['href'])
    else:
        onenews['detail']='该网页不规范'
    return(onenews)

def getnews(pageurl): #将取得单页内容的代码包装成函数
    res=requests.get(pageurl)
    res.encoding='utf-8'
    soup =BeautifulSoup(res.text,'html.parser') 
    newsls=[] #单页新闻list列表
    for news in soup.select('.catlist'):
        for news2 in news.select('.catlist_li'):
            if len(news2)>0:
                newsls.append(getonenews(news2)) #把单条新闻字典加入列表
                #break
    return(newsls)
#print(getnews('http://www.aopa.org.cn/news/list-8.html'))


newstotal=[] #所有新闻列表
aopaurl='http://www.aopa.org.cn/news/list.php?catid=8'
newstotal.extend(getnews(aopaurl)) #获取首页全部内容并加入所有新闻列表

for i in range(2,3):#构造首页以外的网址,获取首页之后全部内容并加入所有新闻列表
    listurl=('http://www.aopa.org.cn/news/list-8-{}.html'.format(i))
    newstotal.extend(getnews(listurl))

#print(len(newstotal))

#print(detailwc(newstotal))
showordcloud(detailwc(newstotal))

df = pandas.DataFrame(newstotal)
#print(df.head())
#print(df['detail'])

df.to_excel('AOPAnews.xlsx')

with sqlite3.connect('AOPAnewsdb.sqlite') as db:
    df.to_sql('AOPAnewsdb',con=db)

 

 

 

posted @ 2017-10-27 00:43  14郭子维  阅读(294)  评论(0编辑  收藏  举报