爬虫大作业


 

1.选一个自己感兴趣的主题(所有人不能雷同)。

2.用python 编写爬虫程序,从网络上爬取相关主题的数据。

3.对爬了的数据进行文本分析,生成词云。

4.对文本分析结果进行解释说明。

5.写一篇完整的博客,描述上述实现过程、遇到的问题及解决办法、数据分析思想及结论。

6.最后提交爬取的全部数据、爬虫及数据分析源代码。

 

1.我选取的是糗事百科里面的 24小时专栏  网址是:https://www.qiushibaike.com/hot/,编译语言是 python,工具是pycharm

2.爬取过程

  F12打开开发者工具 找到需要的内容

  

 可以清晰的看到信息都包含在<div class="content-block clearfix"></div> 中所以我们从其中找需要的内容

  这里我选取段子内容和up主截图分别如下

这里可以清楚的知道 'up主'信息和'段子内容'都包含在<div id="content-left" class="col1"></div>中

  其中‘up主’信息包含在 <h2>标签中,并且包含在<div class="article block untagged mb15 typs_long"></div>中,所以我们获取 'up主'信息的代码可以写为:

1 up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('a')[1].text.strip('\n')

  而 '段子内容'包含在<div class="content"></div>的盒子中,并且包含在<div class="article block untagged mb15 typs_long"></div>中,所以我们获取'段子内容'信息的代码可以写为:

content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')

但是呢,有的用户会以匿名方式发段子(大概害羞吧!!),会出现 一个错误:list out if range,那么该怎么办呢?

答案在最后。

  获取完单个需要的信息之后就是获取整页信息,想法是利用for循环获取,因为上述内容都包含在<div class="article block untagged mb15 typs_long"></div>中,代码如下:

  

1         for content_nums in range(sum_contents):
2             time.sleep(0.2)
3             duanzi_list.append(getContet(url, content_nums))

   获取总的内容数目,思路是看HTML代码,发现每个子项目都包含在<div id="content-left" class="col1"></div>中,所以可以得到其长度确定一页的总子项目数目代码如下:

1 def getAllContents(url):
2     # global onePage_AllContents
3     request = requests.get(url)
4     request.encoding = 'utf-8'
5     soup = BeautifulSoup(request.text,'html.parser')
6 
7     #一页总内容数
8     onePage_AllContents = soup.select('#content-left')[0].select('.mb15').__len__()
9     return onePage_AllContents

  获取完单页,接下来就应该获取所有页面,

1 #获取总页数
2 def getAllPages(url):
3     request = requests.get(url)
4     request.encoding = 'utf-8'
5     soup = BeautifulSoup(request.text,'html.parser')
6 
7     number = int(soup.select('.page-numbers')[-1].text)
8     return number

  将上述综合起来,写到一个function中,获取所有up主信息和段子内容:

 

def dict_Contents(url):
    request = requests.get(url)
    request.encoding = 'utf-8'
    soup = BeautifulSoup(request.text, 'html.parser')
    # time.sleep(1)
    duanzi_list = []
    sum_pages = getAllPages(url)  # 总页数
    sum_contents = getAllContents(url)
    for page_nums in range(1, 4):
        url = 'http://www.qiushibaike.com/hot/page/{0}/'.format(page_nums)
        time.sleep(1)
        for content_nums in range(sum_contents):
            time.sleep(0.2)
            duanzi_list.append(getContet(url, content_nums))
    # for news in duanzi_list:
    #     print(news)
    return duanzi_list

由于我怕页面未完全加载,可能会出现信息获取错误,就添加一个time.sleep作为延迟,由于页面较多,所以值选取了(1,4)的值。

 

   之后呢,应该生成Excel表,所以利用pandas第三方类库生成Excel表

  import pandas
    df = pandas.DataFrame(list_Allduanzi)
    df.to_excel('duanzi.xlsx', engine='xlsxwriter')

  截图:

  

  将要分词的内容放进duanzi.txt中,代码如下:

 

1 def writeNewsDetail(content):
2     f = open('duanzi.txt', 'a', encoding='utf-8')
3     f.write(content)
4     f.close()

 

  截图如下:

  有了内容之后,接下来就是分词,我分词的类库选择的是jieba分词,是一个比较好的分词,在pycharm中可以直接搜索添加,也可以在命令行中添加 指令是'pip install jieba',但是在命令行中添加需先配置环境变量。那么分词的话,首先,要去掉标点符号。将内容中的标点符号等分隔符全部替换为空格。接着,进行分词切割,(同时我们可以去掉我们不需要的信息放在一个集合里)进行词频统计。并保存在文件中,代码如下:

  

 1  import jieba
 2     file = open('duanzi.txt', 'r', encoding='utf-8')
 3     duanzi = file.read()
 4     file.close()
 5 
 6     sep = '''-/.。""'',!?;:~`·[] \ ,:;“”?!-、}{【】‘’'''
 7     exclude = {' ','\ue412','\x01','','','','','','我们','','……',''}
 8 
 9     for char in sep:
10         duanzi = duanzi.replace(char,'')
11     duanziList = list(jieba.cut(duanzi))#分词
12     duanziDict = {}
13     duanzis = list(set(duanziList)-exclude)#删除非中国汉语字符
14 
15     for d in range(0,len(duanzis)):
16         duanziDict[duanzis[d]] = duanzi.count(str(duanzis[d]))
17 
18     dictList = list(duanziDict.items())
19     dictList.sort(key=lambda x:x[1],reverse=True)
20 
21     f = open('count.txt','a',encoding='utf-8')
22     for i in range(150):
23         print(dictList[i])
24         f.write(dictList[i][0] + ':' + str(dictList[i][1]) + '\n')
25     f.close()

  截图结果如下:

  最后一步就是生成词云了。首先是下载,但是呢在pycharm和命令行下载是行不通的需要通过下载被的文件在使用命令行才行,问题解决有提及。那么代码是:

 

 1     #生成词云
 2     from PIL import Image, ImageSequence
 3     import numpy as np
 4     import matplotlib.pyplot as plt
 5     from wordcloud import WordCloud, ImageColorGenerator
 6 
 7     font = r'C:\Windows\Fonts\simhei.TTF'
 8     image = Image.open('./qiushibaike.jpg')
 9     graph = np.array(image)
10     wc = WordCloud(font_path=font, background_color='White', max_words=50, mask=graph)
11     wc.generate_from_frequencies(duanziciyun)
12     image_color = ImageColorGenerator(graph)
13     plt.imshow(wc)
14     plt.axis("off")
15     plt.show()

 

  词云图片形状是(根据那个糗事百科的背景图):

  生成的词云截图如下:

 

  总的代码如下:

 

  1 # -*- coding: UTF-8 -*-
  2 import requests
  3 import re
  4 from bs4 import BeautifulSoup
  5 import time
  6 import openpyxl
  7 import xlsxwriter
  8 
  9 #保存到文本
 10 def writeNewsDetail(content):
 11     f = open('duanzi.txt', 'a', encoding='utf-8')
 12     f.write(content)
 13     f.close()
 14 
 15 #获取
 16 def getContet(url,index):
 17     global up, content
 18     request = requests.get(url)
 19     request.encoding = 'utf-8'
 20     soup = BeautifulSoup(request.text,'html.parser')
 21 
 22     duanzi = {}  # 用字典存放信息
 23 
 24     #up主
 25     try:
 26         up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('a')[1].text.strip('\n')
 27         #内容
 28         content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')
 29     except IndexError:
 30         up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('h2')[0].text.strip('\n')
 31         content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')
 32     duanzi['up主'] = up
 33     duanzi['段子内容'] = content
 34     writeNewsDetail(content)
 35     return duanzi
 36 
 37 #获取总页数
 38 def getAllPages(url):
 39     request = requests.get(url)
 40     request.encoding = 'utf-8'
 41     soup = BeautifulSoup(request.text,'html.parser')
 42 
 43     number = int(soup.select('.page-numbers')[-1].text)
 44     return number
 45 
 46 #获取总的段子数目
 47 def getAllContents(url):
 48     # global onePage_AllContents
 49     request = requests.get(url)
 50     request.encoding = 'utf-8'
 51     soup = BeautifulSoup(request.text,'html.parser')
 52 
 53     #一页总内容数
 54     onePage_AllContents = soup.select('#content-left')[0].select('.mb15').__len__()
 55     return onePage_AllContents
 56 
 57 # 将所有段子存放到字典中
 58 def dict_Contents(url):
 59     request = requests.get(url)
 60     request.encoding = 'utf-8'
 61     soup = BeautifulSoup(request.text, 'html.parser')
 62     # time.sleep(1)
 63     duanzi_list = []
 64     sum_pages = getAllPages(url)  # 总页数
 65     sum_contents = getAllContents(url)
 66     for page_nums in range(1, 4):
 67         url = 'http://www.qiushibaike.com/hot/page/{0}/'.format(page_nums)
 68         time.sleep(1)
 69         for content_nums in range(sum_contents):
 70             time.sleep(0.2)
 71             duanzi_list.append(getContet(url, content_nums))
 72     # for news in duanzi_list:
 73     #     print(news)
 74     return duanzi_list
 75 
 76 
 77 if __name__ == '__main__':
 78     url = 'http://www.qiushibaike.com/hot/'
 79     # request = requests.get(url)
 80     # request.encoding = 'utf-8'
 81     # soup = BeautifulSoup(request.text, 'html.parser')
 82     list_Allduanzi = []
 83     list_Allduanzi = dict_Contents(url)
 84     #生成excel表
 85     import pandas
 86     df = pandas.DataFrame(list_Allduanzi)
 87     df.to_excel('duanzi.xlsx', engine='xlsxwriter')
 88 
 89     import jieba
 90     file = open('duanzi.txt', 'r', encoding='utf-8')
 91     duanzi = file.read()
 92     file.close()
 93 
 94     sep = '''-/.。""'',!?;:~`·[] \ ,:;“”?!-、}{【】‘’'''
 95     exclude = {' ','\ue412','\x01','','','','','','我们','','……',''}
 96 
 97     for char in sep:
 98         duanzi = duanzi.replace(char,'')
 99     duanziList = list(jieba.cut(duanzi))#分词
100     duanziDict = {}
101     duanzis = list(set(duanziList)-exclude)#删除非中国汉语字符
102 
103     for d in range(0,len(duanzis)):
104         duanziDict[duanzis[d]] = duanzi.count(str(duanzis[d]))
105 
106     dictList = list(duanziDict.items())
107     dictList.sort(key=lambda x:x[1],reverse=True)
108     duanziciyun = {}
109     f = open('count.txt','a',encoding='utf-8')
110     for i in range(150):
111         f.write(dictList[i][0] + ':' + str(dictList[i][1]) + '\n')
112         duanziciyun[dictList[i][0]] = dictList[i][1]
113     f.close()
114 
115     #生成词云
116     from PIL import Image, ImageSequence
117     import numpy as np
118     import matplotlib.pyplot as plt
119     from wordcloud import WordCloud, ImageColorGenerator
120 
121     font = r'C:\Windows\Fonts\simhei.TTF'
122     image = Image.open('./qiushibaike.jpg')
123     graph = np.array(image)
124     wc = WordCloud(font_path=font, background_color='White', max_words=50, mask=graph)
125     wc.generate_from_frequencies(duanziciyun)
126     image_color = ImageColorGenerator(graph)
127     plt.imshow(wc)
128     plt.axis("off")
129     plt.show()

 

 

 

3.遇到的问题以及解决办法 

   第一个问题是:上述一开始提及到的,有些up主并非公开的,是匿名用户,它的结构和非匿名用户不一样,那么,我就点击查看,发现只有<span>标签并没<h2>标签,所以我的代码修改如下:

1 #up主
2     try:
3         up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('a')[1].text.strip('\n')
4         #内容
5         content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')
6     except IndexError:
7         up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('h2')[0].text.strip('\n')
8         content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')  

  问题就解决了,其中还学习到了,当 出现错误 'list out of range'时,可以运用try except IndexEorro 处理和寻找问题的根源。

  第二个问题是:在利用pandas库生成excel表时,产生了错误 'openpyxl.utils.exceptions.IllegalCharacterError',我解决的办法是在google搜索该问题,然后在stackflow中找到了答案,下载并且导入 ‘import xlsxwriter’ 然后修改导入数据到excel的代码 ‘df.to_excel('duanzi.xlsx', engine='xlsxwriter')’就OK了。

  第三个问题是:词云wordcloud载pycharm下载不成功,原因是找不到该文件的详情信息,估计是该工具引进python第三方类库有问题,利用pip进行安装也不成功,那么问题就渐渐浮出水面了,就是匹配不到该文件的版本号,所以,我们需要知道该版本号,上网查了下,因为我的python是3.6版本,所以对应cp36,然后我的是windows系统,所以在LDF中下windows版本的,链接是:https://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud,下载amd的,拖入你的python路径中,具体文件目录就自行百度吧(我忘记了!!!)。

我是用anacanda 进行引进该第三方类库的,参考链接:https://www.jianshu.com/p/e4b24a734ccc。

  问题大概就这么多了。

 

 4.数据分析思想以及结论

获取段子内容并且进行词频统计,就可以了解现在的人说的是什么梗,或者有什么关键词特别突出即,当你讲笑话或者处于尴尬情况是可以将一两个笑话和谐一下气氛,也可以用这写梗去交朋友或者哄别人开行,(哄女孩子什么的我没说。。哈),总之是很有用的,但是呢,我不晓得为什么生成的都是一个一个词的,并没有很多词组,不知道是不是结巴分词的一个缺点。

 
 
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM