这段时间发现越来越痴迷于Python,特别是Python3,所以一边看书,一边就想动手做点实践。由于实验室有收集新闻语料的需求,所以就想着以凤凰网新闻网址为目标,试着写一个爬虫如何? 结果还真实现了! 当然 只是入门级的哦,请各位看官多提意见。
工具:python3, Beautiful Soup4
基本思想:先给定一个目标url,它应该是一个索引类型页面(如http://news.ifeng.com/),然后以广度优先的思路 去分析这个url中包含的具体新闻页面链接和其它索引页面链接的页面。接着以迭代的思想,获取其下层索引页面中包含的所有新闻页面链接和索引页面链接,直至当前站下索引页面都处理完。最后提取具体新闻页面的内容
原理图:
具体代码:
说明:如果只考虑收集页面url而不考虑抓取其中的内容,那么可以无视getContent()方法。 由于本人希望能够抓取具体的新闻内容,而且只是实验该方法的可行性,所以选取了范围较小的凤凰国际新闻,根据凤凰新闻具体标签结构来识别其中的时间、标题、正文等。也就是说,如果要抓取其它网站内容的话,getContent()方法中的目标标签也要作相应的修改。本人尚未尝试。
from urllib.request import urlopen
from bs4 import BeautifulSoup
import time
#所需变量初始化及准备工作
#记录程序开始时间
start = time.clock()
#创建一个list用于保存要抽取的网站
rooturl=input('请输入起始目录网址:')
#创建一个list用于保存索引型页面的url
indexlist=[]
#创建一个list用于保存具体内容页面的url
pagelist=[]
##====================以下为方法========================##
'''
方法名:parseHref
作用:从参数给定的url中解析出其中包含的索引类url和具体页面类url,并分别保存到不同的list中,同时确保值唯一
参数:
url:要解析的网址
'''
#获取解析结果
def parseHref(url):
rawtext=urlopen(url).read() #抓取当前页面
soup = BeautifulSoup(rawtext) #使用bs模块获取其结构树
newslinks=soup.findAll("a") #从中找到所有链接标签
for a in newslinks: #循环处理所有a标签
currentLink=a.get('href') #获取当前标签的链接地址
if currentLink and currentLink.find(url)==0: # 如果不为空,则包含有当前要解析的网址,则说明网址初步合法,不会跳转到外部链接
if currentLink.find('detail_')>0: # 如果地址中含有detail_子串,说明这是一个具体页面
if currentLink in pagelist: #判断该页面在pagelist中是否存在 如果存在
print(' 地址已经存在,不处理') # 不处理
else: #如果不存在
pagelist.extend([currentLink]) #则新增进去
print('具体页面list新增:',currentLink)
elif currentLink.endswith('/'): 如果当前地址是以/结尾,说明这是一个索引页面,也就是说它下面还有下级页面
if currentLink in indexlist: # 判断该页面在indexlist中是否存在 如果存在
print(' 地址已经存在,不处理') #不处理
else: # 如果不存在,
indexlist.extend([currentLink]) # 则新增进去
print('索引页面list新增:',currentLink)
'''
方法名:getContent
作用:从pagelist中的url中解析出时间、标题、正文内容,并保存到本地文本中
参数:无参数
'''
def getContent():
#解析当前Pagelist列表中保存的所有具体内容页面
print('解析具体页面')
for p in pagelist:
currentPage=urlopen(p).read()
currentText=BeautifulSoup(currentPage)
print(p)
#获取新闻发布时间
newstime=currentText.find('span',{'itemprop':'datePublished'})
if newstime:
newstime=newstime.get_text().replace('年','-')
newstime=newstime.replace('月','-')
newstime=newstime.replace('日','')
newstime=newstime.replace(':',':')
#获取新闻标题
newstitle=currentText.find("h1")
if len(newstitle)>0:
#print(newstitle.get_text())
newstitle=newstitle.get_text().replace('\t','')
newstitle=newstitle.replace('/','/')
#获取新闻正文
newscontent= currentText.find(id="main_content" )
if newscontent:
#以时间和标题为文件名,创建txt文件,并写入正文内容
f=open('file/'+newstime+" "+newstitle+'.txt','w+', encoding='utf-8')
f.write(newscontent.get_text())
print(newstime+" "+newstitle+'.txt')
f.close()
print('处理完成:',len(pagelist),'个页面。')
#开始爬取
# 1、先解析根目录
print('解析根目录')
parseHref(rooturl)
print('根目录解析完成')
# 2、分析indexlist中的值迭代进行解析,直至所有索引页面都被分析过
print('解析获取的索引页面')
for i in indexlist:
parseHref(i)
print('索引页面解析完成')
#3、解析pagelist中所有具体页面
getContent()
#4、计算程序执行过程耗时
end = time.clock()
print (end-start)
结果截图: