美文网首页
一个简单的爬虫——新闻爬虫

一个简单的爬虫——新闻爬虫

作者: 老白和他的爬虫 | 来源:发表于2019-03-14 15:22 被阅读0次

    公众号的第一篇文章,就先来介绍一下我做的最多的也是最简单的新闻爬虫吧。这个爬虫本身是用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. 获取每一个地址中的新闻链接
    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,后面会陆续分享一些技术学习的文章,希望能对你有帮助。

    相关文章

      网友评论

          本文标题:一个简单的爬虫——新闻爬虫

          本文链接:https://www.haomeiwen.com/subject/jomapqtx.html