1.requests发送请求,BeautifulSoup剖析页面
PS:requests使用文档
import requests
from bs4 import BeautifulSoup
url='http://news.sina.com.cn/c/nd/2018-04-17/doc-ifzfkmth5545198.shtml'
res=requests.get(url)
res.encoding='utf-8'#网页乱码问题
soup=BeautifulSoup(res.text,'html.parser')#使用html解析器解析请求内容
2.抓取新闻内容详情
使用浏览器的开发者工具,分析页面中的元素和结构
使用BeautifulSoup的select方法获取页面中的元素,返回的是一个list列表
①获取标题
soup.select('.main-title')[0].text #通过select方法获取到标签列表,通过下标[0]取得列表中的元素
②获取时间
PS:视频当时的页面元素中,时间信息没有类选择器,包含在通过.date-source筛选出来的span标签下,通过contents取得
from datetime import datetime
time=soup.select('.date-source')[0].contents[1].text #contents获取元素集合中的每个元素
dt=datetime.strptime(time,'%Y年%m月%d日%H:%M:%S') #通过datetime的strptime将日期字符串转换为时间
timesource=dt.strftime('%Y%m%d %H:%M:%S') #通过strftime将日期格式转换为格式化的时间格式字符串
③获取编辑
soup.select('.show_author')[0].text.lstrip('责任编辑:') #lstrip()去除字符
④获取文章
article=[]
for p in soup.select('#article p')[:-2]:#取得ID选择器下的标签元素,从元素集合中取得第一个到倒数第3个
article.append(p.text.strip()) #将取得的段落元素内容通过strip()去除空格之后加入到列表中
''.join(article) #将列表中的元素通过join连接,得到完成的文章
⑤获取评论数
评论数从js中的接口获得,且通过观察评论数的接口链接与新闻链接相关,整合成一个函数
import re
import json
def getComment(url): #url为新闻详情链接
#通过观察获取评论的接口链接如下,末尾花括号{}可带入参数
commentforurl='http://comment5.news.sina.com.cn/page/info?version=1&format=json&channel=gn&newsid=comos-{}'
newsid=re.search('doc-i(.+).shtml',url).group(1) #用到正则表达式需导入re,通过观察用search()得到作为关联的newsid;
#newsid=url.split('/')[-1].lstrip('doc-i').rstrip('.shtml') #也可通过split()和strip
commenturl=requests.get(commentforurl.format(newsid)) #通过format()得到完成的接口链接
jd=json.loads(commenturl.text.lstrip('jsonp_1523978275766(').rstrip(')'))#导入json模块,通过loads()将处理后的字串转化为字典
comment=jd['result']['count']['total']
return comment
3.将新闻详情整合成一个函数,将新闻中的标题、时间、编辑、文章和评论数,保存至字典中
def getNewsDetail(url):
res=requests.get(url)
res.encoding='utf-8'
result={}
soup=BeautifulSoup(res.text,'html.parser')
result['title']=soup.select('.main-title')[0].text
time=soup.select('.date-source')[0].contents[1].text
dt=datetime.strptime(time,'%Y年%m月%d日%H:%M:%S')
result['time']=dt.strftime('%Y%m%d %H:%M:%S')
result['editor']=soup.select('.show_author')[0].text.lstrip('责任编辑:')
article=[]
for p in soup.select('#article p')[:-2]:
article.append(p.text.strip())
result['article']= ''.join(article)
result['comment']=getComment(url)
return result
4.取得将新闻列表的每个新闻链接带入到新闻详情函数,将返回的新闻详情保存至列表
def getLinklist(url):#url为每页新闻列表链接
res=requests.get(url)
jd=json.loads(res.text.lstrip(' newsloadercallback(').rstrip(');'))
linkdetaillist=[]
for links in jd['result']['data']:#获取新闻列表中的新闻链接
linkdetaillist.append(getNewsDetail(links['url']))#调用新闻详情链接,将结果保存至列表中
return linkdetaillist
5.将批次抓取的每页新闻列表整理至list中,使用Pandas整理保存为excel文件
import pandas
url='http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gnxw&cat_2==gdxw1||=gatxw||=zs-pl||=mtjj&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page={}'
news_total=[]
for i in range(1,3):
newsurl=url.format(i)
newsary=(newsurl)
news_total.extend(newsary)#extend()函数在列表中添加newsary中的多个值
df=pandas.DataFrame(news_total)
df.to_excel('news.xlsx') #保存至当前目录下,文件为news.xlsx