本篇文章主要对新浪新闻进行python爬虫爬取。
爬取的新浪网页:关于开学,钟南山说这两点非常重要!
点击右键检查
,根据网页的结构可以获取我们想要的信息。接下来爬取新闻的标题、时间、来源、内容、责任编辑。
import requests
from bs4 import BeautifulSoup
from datetime import datetime
#获取网页源代码
res = requests.get('https://news.sina.com.cn/c/2020-04-12/doc-iirczymi5906268.shtml')
#设置编码格式
res.encoding = 'utf-8'
#创建BeautifulSoup对象
soup = BeautifulSoup(res.text,'html.parser')
#获取标题
title = soup.select('.main-title')[0].text
#获取时间
timesource = soup.select('.date')[0].text
time = datetime.strptime(timesource,'%Y年%m月%d日 %H:%M')
#获取来源
source = soup.select('.source')[0].text
#获取内容
article = ' '.join([i.text.strip() for i in soup.select('.article p')[:-1]])
#获取责任编辑
author = soup.select('.show_author')[0].text.lstrip('责任编辑:')
接下来获取评论数,由于新浪新闻中的评论数不再html文件中而在js文件中。我们需要获取评论的js文件。
复制评论的URL:https://comment.sina.com.cn/page/info?version=1&format=json&channel=gn&newsid=comos-irczymi5906268&group=0&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=3&t_size=3&h_size=3&thread=1&uid=unlogin_user&callback=jsonp_1586701508631&_=1586701508631
下载评论数据,去掉元素URL末尾的&callback=jsonp_1586701508631&_=1586701508631
会得到一个json格式的数据
comments = requests.get('https://comment.sina.com.cn/page/info?version=1&format=json&channel=gn&newsid=comos-irczymi5906268&group=0&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=3&t_size=3&h_size=3&thread=1&uid=unlogin_user')
comments.encoding = 'utf-8'
comments.text
num = json.loads(comments.text)['result']['count']['total']
num
import re
newsurl = 'https://news.sina.com.cn/c/2020-04-12/doc-iirczymi5906268.shtml'
newsid = re.search('doc-i(.+).shtml',newsurl)
newsid.group(1)
新浪国内新闻https://news.sina.com.cn/china/
最下面为分页的切换。
分页是动态加载的,通过network找到分页相关的URL,不同的分页链接有2处不同,如下:
接着我们获取新浪新闻首页新闻信息,采用的是api的方式获取。
新浪首页的api为:
https://feed.sina.com.cn/api/roll/get?pageid=121&lid=1356&num=20&versionNumber=1.2.4&page=2&encode=utf-8
import requests
import json
#获取新浪新闻首页新闻信息
res = requests.get('https://feed.sina.com.cn/api/roll/get?pageid=121&lid=1356&num=20&versionNumber=1.2.4&page=1code=utf-8')
res = json.loads(res.text)
res
for i in res['result']['data']:
print(i['url'])
jieba是python中用于分词的第三方库。
jieba中文分词的主要原理:
利用一个中文词库,确定中文字符之间的关联概率,中文字符间概率大的组成词组,形成分词结果
jieba库分词的三种模式:
精确模式 | 把文本精确的切分开,不存在冗余单词 |
---|---|
全模式 | 把文本中所有可能的词语都扫描出来,有冗余 |
搜索引擎模式 | 在精确模式的基础上,对长词再次切分 |
jieba库常用函数:
jieba.lcut(s) | 精确模式,返回一个列表类型的分词结果 |
jieba.lcut(s,cut_all=True) | 全模式,返回一个列表类型的分词结果,存在冗余 |
jieba.lcut_for_search(s) | 搜索引擎模式,返回一个列表类型的分词结果,存在冗余 |
jieba.add_word(w) | 向分词词典增加新词w |
import requests
from bs4 import BeautifulSoup
import json
import re
from datetime import datetime
import pandas as pd
import sqlite3
import os
import jieba
#新浪首页api
url = 'https://feed.sina.com.cn/api/roll/get?pageid=121&lid=1356&num=20&versionNumber=1.2.4&page={}&encode=utf-8'
#评论链接
commentUrl = 'https://comment.sina.com.cn/page/info?version=1&format=json\
&channel=gn&newsid=comos-{}&group=undefined&compress=0&ie=utf-8&oe=utf-8\
&page=1&page_size=3&t_size=3&h_size=3&thread=1&uid=3537461634'
# 爬取网页内详细信息
def getNewsDetail(newsurl):
result = {}
#print('newsurl:',newsurl)
res = requests.get(newsurl)
res.encoding = 'utf=8'
soup = BeautifulSoup(res.text, 'html.parser')
result['title'] = soup.select('.main-title')[0].text
timesource = soup.select('.date-source')[0].select('.date')[0].text
# dt = datetime.strptime(timesource,'%Y年%m月%d日 %H:%M')
result['time'] = timesource
result['url'] = newsurl
result['origin'] = soup.select('.date-source')[0].text
result['article'] = ' '.join([p.text.strip() for p in soup.select('#article p')[:-1]])
result['author'] = soup.select('.show_author')[0].text.lstrip('责任编辑:')
result['comments'] = getCommentCounts(newsurl)
return result
# 爬取评论数量,两条不同链接的评论,
#不同的地方是newsid=comos-xxxx部分不一样,xxx为新闻标识符(newsid),可以用{}来代替,之后用format()函数填充
def getCommentCounts(newsurl):
m = re.search('doc-i(.+).shtml', newsurl)
newsId = m.group(1)
commentURL = commentUrl.format(newsId)
comments = requests.get(commentURL)
jd = json.loads(comments.text)
return jd['result']['count']['total']
# 获取每个分页的所有新闻的URL,然后取得详细信息
def parseListLinks(url):
newsdetails = []
res = requests.get(url)
jd = json.loads(res.text)
for ent in jd['result']['data']:
newsdetails.append(getNewsDetail(ent['url']))
return newsdetails
news_total = []
# 取得指定分页的新闻信息
for i in range(1, 2): # 取第一页的新闻信息
newsurl = url.format(i)
newsary = parseListLinks(newsurl)#返回的是每个分页的新闻的信息的列表,列表元素是包含每个新闻具体信息的字典
news_total.extend(newsary)
#用pandas整理爬取出的资料
df = pd.DataFrame(news_total)
# 指定生成的列顺序
cols = ['title', 'author', 'time', 'origin', 'article', 'comments', 'url']
df = df.loc[:, cols]
# 存储到sqlite数据库中
with sqlite3.connect('news.sqlite') as db:
df.to_sql('newsInfo', con=db)
# 读取数据库中的信息
with sqlite3.connect('news.sqlite') as db1:
df2 = pd.read_sql_query('SELECT * FROM newsInfo', con=db1)
# 保存新闻信息到excel表格中
df2.to_excel('newsDetails2.xlsx')
excelFile = r'newsDetails2.xlsx'
#读取excel的数据
data = pd.read_excel(excelFile,sheet_name=0)
#获取标题项并进行分词
for i in range(20):
res=jieba.cut(data['title'][i])
print("/".join(res))
代码:
from wordcloud import WordCloud
import jieba
import numpy
import PIL.Image as Image
import pandas as pd
excelFile = r'C:\Users\Petrichor\Desktop\信息内容安全\爬虫\demo1\newsDetails2.xlsx'
data = pd.read_excel(excelFile,sheet_name=0)
with open('word.txt','a') as file:
for i in range(20):
file.write(data['title'][i])
file.write('\n')
def chinese_jieba(text):
wordlist_jieba=jieba.cut(text)
space_wordlist=" ".join(wordlist_jieba)
print(space_wordlist)
return space_wordlist
with open("word.txt")as file:
text=file.read()
text=chinese_jieba(text)
#2.图片遮罩层
mask_pic=numpy.array(Image.open("img1.png"))
#3.将参数mask设值为:mask_pic
wordcloud = WordCloud(font_path="C:/Windows/Fonts/simfang.ttf",mask=mask_pic,background_color='white').generate(text)
image=wordcloud.to_image()
image.show()
最终结果:
参考博客:
python3编程05–爬虫实战:爬取新闻网站信息1
python3编程06–爬虫实战:爬取新闻网站信息2
python3编程07-爬虫实战:爬取新闻网站信息3