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

2019-03-14  本文已影响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获取翻页链接

首先我们想一个问题,我们自己在浏览新闻网站时,需要进行翻页,同样我们的爬虫也需要获取到目标网页的翻页地址


翻页

这里需要两步:

检查源代码发现翻页标签链接中包含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,后面会陆续分享一些技术学习的文章,希望能对你有帮助。

上一篇下一篇

猜你喜欢

热点阅读