公众号的第一篇文章,就先来介绍一下我做的最多的也是最简单的新闻爬虫吧。这个爬虫本身是用java写的,搭载在我之前项目的服务器上,今天用python实现一下。这个爬虫我也给别人讲过很多次,在双创之星的舞台上讲过,在新生导航课上讲过(两次),在课堂上讲过。其实现在回头看一下这个爬虫真的很low很简单,但好歹也是我花了很久学习的,今天就系统的用python来实现一下吧。
新闻爬虫
- 单个网页信息爬取
- 多个网页链接爬取
- 整合模块代码
1.单个网页信息爬取
1.1获取目标网址信息
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/info/1009/7267.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
print(req.text)
我选取的网址是华师信管官网。在这段代码中我们通过一个requests.get()
来获取了目标对象,你可以把这一步理解为用浏览器打开了一个网页。这里记住把编码格式通过req.encoding
进行统一,避免出现乱码的情况。最后一行是输出这个网页的源码
1.2.提取目标网址信息
我们使用浏览器打开具体的网页,查看我们需要的信息
谷歌浏览器可以直接通过检查查看到我们需要的信息在哪里
我们可以看到我们所需要的文本信息都在
class="sub_r_con sub_r_intro"
的div
中。到这里我们要明确下我们所需要的信息到底是什么(其实这一步在你写爬虫前就要确定好)。这里我们需要的是新闻标题、日期、作者、正文,那么下面我们就要逐个击破
1.2.1获取标题
同样的我们检查标题所在的位置
我们发现这个标题在
<h1>
中,下面通过代码来获取
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/info/1009/7267.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
title = bf.find_all('h1') #获取页面所有的h1标签
print(title)
一行一行来读代码其实很好理解,前面我们获取了网页的源代码。通过bf = BeautifulSoup(html,'lxml')
来对网页进行解析,讲解析后的网页结构赋予bf
。这里说明一下,lxml是一个参数,后面我会在专门学习BeautifulSoup的板块来学习。
我们将包含所有的<h1>
模块赋予给title
,这一步通过bf.find_all()
来实现,这个也很好理解,解析后的网页分模块赋予给了bf
,我们通过bf.find_all()
这一操作找到<h1>
的标签并将其赋予给title
但当我们输出这段代码的时候问题来了
这是因为整个页面不止一个
<h1>
标签,只有第三个标签符合我们的要求,只需要对代码稍作修改就可以实现最终想要达到的效果
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/info/1009/7267.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
titles = bf.find_all('h1') #获取页面所有的h1标签
title = titles[2].text#提取最后一个节点转换为文本
print(title)
1.2.2获取日期和作者
同样我们找到日期和作者所在的div
标签,发现它的类别为class_="cz"
,进行提取。
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/info/1009/7267.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
author_date = bf.find_all('div',class_="cz") #获取页面的作者和日期
print(author_date[0].text)
这里多说一句,即使模块中只含有一个标签,也得用列表的形式表示出元素,就像这里的author_date
一样,不然会报错
1.2.3获取正文
相信你前面都实现了的话,这一步你也会很熟练了。首先找到正文所在div
为类别class="normal_intro"
,修改一下前面的代码即可
from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/info/1009/7267.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
article = bf.find_all('div',class_="normal_intro") #获取页面正文
print(article[0].text)
2.多个网页链接爬取
上面只是对于某一个新闻页面的信息爬取,而我们需要做到的是,给定华师信管的网址,能自动爬取上面所有的网址
2.1获取翻页链接
首先我们想一个问题,我们自己在浏览新闻网站时,需要进行翻页,同样我们的爬虫也需要获取到目标网页的翻页地址
翻页
这里需要两步:
- 识别翻页的
<a>
标签 - 提取网址
检查源代码发现翻页标签链接中包含xydt/
这就好办了,我们通过下面的代码可以得到翻页的链接
from bs4 import BeautifulSoup
import re
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/xwdt/xydt.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
fan_linklist = [] #存入翻页地址
for x in bf.find_all('a',href = re.compile('xydt/')): #找到目标a标签
link = x.get('href') #提取链接
if link:
fan_linklist.append(link) #存入列表
print(fan_linklist)
2.2获取新闻链接地址
通过上面的代码,你只需要找到新闻链接标签特点然后修改代码即可,细心检查可以发现,新闻链接都含有info/
from bs4 import BeautifulSoup
import re
import requests
if __name__ == "__main__":
target = 'http://imd.ccnu.edu.cn/xwdt/xydt.htm' #目标网址
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
xinwen_linklist = [] #存入翻页地址
for x in bf.find_all('a',href = re.compile('info/')): #找到目标a标签
link = x.get('href') #提取链接
if link:
xinwen_linklist.append(link) #存入列表
print(xinwen_linklist)
3.整合代码
好了,做到这步前面都能实现的话,你已经全部明白原理了,嗯....你没有听错,只是明白原理了,写程序最麻烦的就是调试和修改,所以你后面的工作量可能是你前面的几倍
我们再来过一遍这个爬虫的逻辑
- 获取当前地址的翻页地址,也就是下一页地址。此步骤重复,直至获取网站全部的翻页地址
- 获取每一个地址中的新闻链接
- 提取新闻信息
这其中还有一点我们要注意,就是第1,2步我们都要设置一个去重程序,即除去反复爬取的地址,这样保证效率也保护电脑,它好你也好
下面就动手实现啦!
另外需要说明一下,上面的代码片段重在原理,最终的爬虫代码和上面的代码可能稍有出入,但其实都是万变不离其宗
from bs4 import BeautifulSoup
import re
import requests
class downloader(object):
def __init__(self):
self.target = 'http://imd.ccnu.edu.cn/xwdt/xydt.htm' #目标网址
"""
函数说明:获取翻页地址
Parameters:
xiayiye - 下一页地址(string)
Returns:
fanye - 当前页面的翻页地址(list)
"""
def get_fanye_url(self,target):
req = requests.get(target) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
fanye = []
for x in bf.find_all('a',class_="Next"): #找到目标a标签
link = x.get('href') #提取链接
if link:
link = link.replace('xydt/','')
link = "http://imd.ccnu.edu.cn/xwdt/xydt/" + link #将提取出来的链接补充完整
fanye.append(link) #存入列表
return fanye
"""
函数说明:获取新闻地址
Parameters:
fanye - 翻页地址(string)
Returns:
xinwen_linklist - 新闻链接(list)
"""
def get_xinwen_url(self, fanye):
req = requests.get(fanye) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
xinwen_linklist = [] #存入翻页地址
for x in bf.find_all('a',href = re.compile('info/')): #找到目标a标签
link = x.get('href') #提取链接
if link:
link = "http://imd.ccnu.edu.cn" + link.replace('../..','') #将提取出来的链接补充完整
xinwen_linklist.append(link) #存入列表
return xinwen_linklist
"""
函数说明:获取新闻信息
Parameters:
xinwen_url - 新闻链接(string)
Returns:
xinwen - 新闻信息(list)
"""
def get_xinwen(self, xinwen_url):
req = requests.get(xinwen_url) #获取对象
req.encoding = "utf-8" #设置编码格式
html = req.text #获得网页源代码
bf = BeautifulSoup(html,'lxml') #利用BeautifulSoup进行解析
titles = bf.find_all('h1') #获取页面所有的h1标签
title = titles[2].text#提取最后一个节点转换为文本
print("标题:"+title)
author_date = bf.find_all('div',class_="cz")[0].text #获取页面的作者和日期
print("作者和日期:"+author_date)
article = bf.find_all('div',class_="normal_intro")[0].text #获取页面正文
print("正文:"+article)
xinwen = ["标题:"+title,"作者和日期:"+author_date,"正文:"+article]
return xinwen
if __name__ == "__main__":
dl = downloader()
fanye = dl.get_fanye_url(dl.target)
'''
获取全部的翻页链接
'''
for x in fanye:
b = dl.get_fanye_url(x)
for w in b: #这一个循环的目的是获取翻页链接的同时去重
if w not in fanye:
fanye.append(w)
print("翻页链接"+w)
'''
获取每一个翻页链接里的新闻链接
'''
xinwen_url = []
for x in fanye:
a = dl.get_xinwen_url(x)
for w in a: #这一个循环的目的是获取新闻链接的同时去重
if w not in xinwen_url:
xinwen_url.append(w)
print("新闻地址"+w)
'''
获取每一个新闻链接的新闻信息
'''
xinwen = []
for x in xinwen_url:
xinwen.append(dl.get_xinwen(x))
好了,到这里这个爬虫就已经写好了,直接复制我的代码在编辑器里运行,就可以爬取华师信管官网的所有新闻了,可能 copy这段代码只需要几秒钟,但如果能把每一步的逻辑弄明白,相信你也能很快学会简单的爬虫的。(运行时间大概二十分钟,数据量1200条)
另外我还是想吐槽一下,在这篇文章开头,我说了我觉得这个爬虫很low很简单,但是实际操作起来还是发现花了我两天的时间,当然两天不是全部都在写程序,是在实习期间忙里偷闲写出来的,看来任何事情都是不简单的,一步一步来吧
另外,欢迎关注公众号:老白和他的爬虫,这个是我的个人公众号,文章也会同步发布在简书:Heisenberg_b799,后面会陆续分享一些技术学习的文章,希望能对你有帮助。
网友评论