本次作业的要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2941
前言
本次我爬取的是广州商学院校园新闻的全部信息,即我给出校园新闻的网址,通过网址我们可以爬取校园新闻的作者、发布时间、概述、来源等,由于新闻较多,所以在这里我使用range(41, 51)爬取41-51页的校园新闻的信息。下面,我将从几点来讲解爬取校园新闻信息的步奏,最后第七点是整个爬取的源代码以及运行结果。
1.从新闻url获取新闻详情
第一步已经完成了获取新闻信息的步奏,接着把获取到的新闻内容添加进字典中
# 标题 title = newSoup.select('.show-title')[0].text # 发布信息 newInfo = newSoup.select('.show-info')[0].text # 发布时间 newDT = newsDateTime(newInfo) # 作者 author = newInfo.split()[2].lstrip('作者:') # 审核 examine = newInfo.split()[3].lstrip('审核:') # 来源 source = newInfo.split()[4].lstrip('来源:') # 获取点击次数的url newClick = newsClick(url) # 把获取到的新闻内容添加进字典中 newsDetail = {} newsDetail['newsTitle'] = title newsDetail['newsDaTe'] = newDT newsDetail['newsAuthor'] = author newsDetail['newsExamine'] = examine newsDetail['newsSource'] = source newsDetail['newsClick'] = newClick
2.从列表页的url获取每篇新闻url
因为这里我们用的是广州商学院的校园新闻,其校园新闻列表页是每页有10篇新闻,所以我们要根据新闻页数来获取里面的每篇新闻的url。
完成第一步后,我们接着新建一个newList的空列表,使用遍历的方式获取新闻的url(即代码中的newUrl)、新闻的概述信息,并把新闻的概述信息添加进字典中,最后把字典添加到newList列表中。
newList = [] li = newSoup.select('li') for new in li: if len(new.select('.news-list-text')) > 0: newUrl = new.select('a')[0]['href'] # 获取新闻的概述信息 newDescription = new.select('.news-list-description')[0].text newsDict = newsInfo(newUrl) # 把新闻的概述信息添加进字典中 newsDict['newsDescription'] = newDescription newList.append(newsDict)
3.生成所页列表页的url并获取全部新闻
利用for循环遍历新闻41-51页的列表页的url
allNews = [] # 获取页数为range(41,51)的新闻信息 for i in range(41, 51): listPageUrl = 'http://news.gzcc.cn/html/xiaoyuanxinwen/{}.html'.format(i) allNews.extend(newsList(newsUrl)) newsTable = ps.DataFrame(allNews) print(newsTable) # 测试输出newsTable中的信息
4.设置合理的爬取间隔
很多网站的反爬虫机制都设置了访问间隔时间,一个IP如果短时间内超过了指定的次数就会进入“冷却CD”,再加上本来爬虫就可能会给对方网站造成访问的负载压力,为了你好我也好,建议大家在爬取别的网站的时候设置合理的爬取时间间隔,这种防范既可以从一定程度上防止被封,又可以降低对方服务器的访问压力。
import time import random time.sleep(random.random()*3)
5.用pandas做简单的数据处理并保存成csv文件
在本文中,我把所爬取下来的数据保存到D:\sougo\newsInfo\news.csv中,执行代码如下所示:
newsTable.to_csv(r'D:\sougo\newsInfo\news.csv',encoding='utf-8-sig')
执行结果如图所示:
下图为执行后生成的csv文件
打开生成的news.csv文件,我们可以看到里面的内容如下图所示:
6.保存到数据库
在这里,我使用的是sqlite数据库
import sqlite3 # 把获取到的校园新闻信息保存到数据库中 with sqlite3.connect('newsInfo.sqlite') as db: newsTable.to_sql('news', db) # 查找数据库中的信息并赋给selectNews selectNews = ps.read_sql_query('SELECT * FROM news', con=db) # 输出数据库中点击次数大于200的信息 print(selectNews[selectNews['newsClick']>200])
7.程序源代码
1 # -*- coding: UTF-8 -*- 2 import requests 3 from bs4 import BeautifulSoup 4 from datetime import datetime 5 import re 6 import pandas as ps 7 import sqlite3 8 import time 9 import random 10 11 12 # 获取点击次数 13 def newsClick(url): 14 id = re.findall('(\d{1,7})', url)[-1] 15 clickUrl = 'http://oa.gzcc.cn/api.php?op=count&id={}&modelid=80'.format(id) 16 click = requests.get(clickUrl) 17 time.sleep(random.random() * 3) # 延迟 18 newClick = int(click.text.split('.html')[-1].lstrip("('").rstrip("');")) # 获取点击次数 19 # print('点击次数:') 20 # print(newClick) # 测试输出点击次数 21 return newClick 22 23 # 获取新闻的发布时间 24 def newsDateTime(newInfo): 25 newDate = newInfo.split()[0].lstrip('发布时间:') 26 newTime = newInfo.split()[1] 27 newDateTime = newDate + ' ' + newTime 28 newDT = datetime.strptime(newDateTime, '%Y-%m-%d %H:%M:%S') 29 # print('发布时间:') 30 # print(newDT) 31 return newDT 32 33 34 # 获取新闻的全部信息,并形成字典 35 def newsInfo(url): 36 news = requests.get(url) 37 time.sleep(random.random() * 3) # 延迟 38 news.encoding = 'utf-8' 39 newSoup = BeautifulSoup(news.text, 'html.parser') 40 41 # 标题 42 title = newSoup.select('.show-title')[0].text 43 # print('标题:'+title) # 测试输出标题 44 45 # 发布信息 46 newInfo = newSoup.select('.show-info')[0].text 47 48 # 发布时间 49 newDT = newsDateTime(newInfo) 50 51 # 作者 52 author = newInfo.split()[2].lstrip('作者:') 53 # print(author) # 测试输出作者 54 55 # 审核 56 examine = newInfo.split()[3].lstrip('审核:') 57 # print(examine) # 测试输出审核 58 59 # 来源 60 source = newInfo.split()[4].lstrip('来源:') 61 # print(source) # 测试输出来源 62 63 # 获取点击次数的url 64 newClick = newsClick(url) 65 66 # 内容 67 # newContent = newSoup.select('.show-content')[0].text 68 # print('内容:'+newContent) #测试输出内容,由于一般新闻内容都比较长,所以这里我就不输出新闻的内容了 69 70 # 把获取到的新闻内容添加进字典中 71 newsDetail = {} 72 newsDetail['newsTitle'] = title 73 newsDetail['newsDaTe'] = newDT 74 newsDetail['newsAuthor'] = author 75 newsDetail['newsExamine'] = examine 76 newsDetail['newsSource'] = source 77 newsDetail['newsClick'] = newClick 78 79 return newsDetail; 80 81 # 获取新闻列表的概述信息,并封装成列表 82 def newsList(url): 83 news = requests.get(url) 84 time.sleep(random.random() * 3) # 延迟 85 news.encoding = 'utf-8' 86 newSoup = BeautifulSoup(news.text, 'html.parser') 87 newList = [] 88 li = newSoup.select('li') 89 for new in li: 90 if len(new.select('.news-list-text')) > 0: 91 newUrl = new.select('a')[0]['href'] 92 # 获取新闻的概述信息 93 newDescription = new.select('.news-list-description')[0].text 94 newsDict = newsInfo(newUrl) 95 # 把新闻的概述信息添加进字典中 96 newsDict['newsDescription'] = newDescription 97 newList.append(newsDict) 98 return newList 99 100 url = 'http://news.gzcc.cn/html/2019/xiaoyuanxinwen_0322/11047.html' 101 # print(newsInfo(url)); # 测试输出newsInfo(url)中的信息 102 103 newsUrl = 'http://news.gzcc.cn/html/xiaoyuanxinwen/' 104 # print(newsList(newsUrl)); # 测试输出newsList(newsUrl)中的信息 105 106 # 获取新闻的总页数 107 # page = int(newSoup.select('#pages')[0].text.split('..')[1].rstrip(' 下一页 ')) 108 109 allNews = [] 110 # 获取页数为range(41,51)的新闻信息 111 for i in range(41, 51): 112 listPageUrl = 'http://news.gzcc.cn/html/xiaoyuanxinwen/{}.html'.format(i) 113 allNews.extend(newsList(newsUrl)) 114 newsTable = ps.DataFrame(allNews) 115 # print(newsTable) # 测试输出newsTable中的信息 116 # newsTable.sort_index(by=['newsClick'],ascending=False) # 按点击次数排名,当ascending=TRUE时是从小到大排列 117 # newsTable.sort_index(by=['newsDaTe'],ascending=False) # 按发布时间进行排名 118 119 # 把获取到的校园新闻信息生成csv文件 120 newsTable.to_csv(r'D:\sougo\newsInfo\news.csv',encoding='utf-8-sig') 121 122 # 把获取到的校园新闻信息保存到数据库中 123 with sqlite3.connect('newsInfo.sqlite') as db: 124 newsTable.to_sql('news', db) 125 # 查找数据库中的信息并赋给selectNews 126 selectNews = ps.read_sql_query('SELECT * FROM news', con=db) 127 # 输出数据库中点击次数大于200的信息 128 print(selectNews[selectNews['newsClick']>200])
运行过后,控制台输出了print(selectNews[selectNews['newsClick']>200])的运行结果如下图,即输出了点击次数大于200的新闻信息。