带你写爬虫(python)第一篇----抓取安徽理工大学新闻网中所有新闻

本文介绍了一种使用Python爬虫技术抓取特定大学新闻网站信息的方法。通过分析目标页面结构,利用requests库获取HTML内容,结合re和BeautifulSoup库解析数据,实现了对新闻标题、发布时间及正文的自动抓取。

最近一直在学习python爬虫,所以一直想写个简单的爬虫教程,所以第一篇就拿母校新闻网官网来练手了,没想到写爬虫的过程还停一波三折的。(后来发现新闻网页面还有访问限制,多次访问后,本机ip就被限制了,本文不讨论这个)

准备工作
- 目标页面:http://news.aust.edu.cn
- 开发工具:pycharm
- python版本:3.6.4
- 所需库:请求库requests,解析库re,BeautifulSoup
- 这里不介绍各种库安装和使用方法,推荐查看
- BS模块:Python爬虫利器二之Beautiful Soup的用法
- re模块: Python爬虫入门七之正则表达式

爬取过程分析
第一步:获取每一个索引页面的url
第二步:解析每一个索引页面,获取每个文章标题和详细页的url等信息
第三步:爬取并解析详情页的相关信息

第一步:分析页面
分析所需爬取页面,浏览器打开页面,主要抓取的就是图片中框住的部分,本文主要介绍第一个“学校要闻”(第二个“综合要闻”类比,该文不赘述)
这里写图片描述

点击“学校要闻”,进入单独的页面:http://news.aust.edu.cn/xxxw.htm,之后按F12进行页面分析
这里写图片描述
查看之后,发现这个这些数据都直接在html里面,不是用ajax加载的,那就比较简单的了。

第二步:爬取索引页
打开pycharm,新建一个工程,在工程里面新建一个文件spider.py
这里写图片描述
定义第一个函数,抓取索引页的html代码,导入requests模块以及对应的异常处理模块,这里使用requests模块进行抓取,未使用urllib库

import requests
from requests.exceptions import RequestException

#抓取索引页面
def get_index_html():
    #目标网页
    url = 'http://news.aust.edu.cn/xxxw.htm'
    try:
        #使用requests的get方法获取url的html全部代码
        response = requests.get(url)
        if response.status_code ==200:
            return response.text
        return None
    except RequestException:
        return None
#主函数
def mian():
    get_index_html()

if __name__ == '__main__':
    main()

如果运行这段代码控制台出现html代码就代表第一步成功了
(若html中这里出现中文乱码,请尝试使用下面的方法)

response = requests.get(url).encoding('utf8')
或者
response.encoding = 'utf8'

若不知道html的编码,可以用

print(response.apparent_encoding)

这样打印出来的就是你的网页的编码方式

第三步:解析索引页
导入re模块,定义一个解析函数,这里使用re模块正则表达式进行匹配解析(当然这里也可以用xpath,BeaytifulSoup等方式,请自行选择)

#导入re模块,用于正则匹配使用
import re
#定义解析索引页函数
def parse_index_html(content):
    #构造正则表达式,使用re.S模式来匹配换行
    pattern = re.compile('<font>(.*?)</font>.*?absmiddle.*?href="(.*?)" target="_blank">(.*?)</a>',re.S)
    #使用findall方法获取所有结果,结果为一个list格式
    results = re.findall(pattern,content)
    print(results)

运行结果
这里写图片描述
当然在这里也可以将结果用字典输出

rooturl = 'http://news.aust.edu.cn/'#详细页url的最前面的根url(https://blog.csdn.net/html%E4%B8%AD%E5%86%99%E7%9A%84%E6%98%AF%E7%9B%B8%E5%AF%B9%E5%9C%B0%E5%9D%80)
for result in results:
        data = {
            'time':result[0],
            'url':rooturl+result[1],#合并成每一页的url
            'content':result[2]
        }
        print(data)

结果是这样
这里写图片描述
当然还需要找出每一页的url,我们点击下一页,查看每一页的url有什么规律,是直接修改的url还是修改的参数
这里写图片描述
这里写图片描述
很明显,总页数283,往下一页的话,url就每次-1,所以我们要在这也要顺便获取一下总页数

#获取总页数
    page_pattern = re.compile('&nbsp;1/(.*?)&nbsp')
    pagenum = re.findall(page_pattern,content)
    pagenum1 = int(pagenum[0])#将str的页数转成int类型,后面循环要用到
    print(pagenum1)

当然,把这个获取页数的代码放到下面获取所有url的函数中可能更好

第四步:获取全部需要抓取的url
定义一个函数

def parse_all_url(content):
    #解析索引页面上的总页数
    page_pattern = re.compile('&nbsp;1/(.*?)&nbsp')
    pagenum = re.findall(page_pattern, content)
    pagenum1 = int(pagenum[0])
    #获取每一页的url
    rooturl = 'http://news.aust.edu.cn/xxxw/'
    #循环构造所有详细页的url
    for page in range(0,pagenum1):
        if page ==0:
            wholeurl = 'http://news.aust.edu.cn/xxxw.htm'
        else :
            wholeurl = rooturl+str(pagenum1-page)+'.htm'
        # print(wholeurl)
        content = get_index_html(wholeurl)#获取索引页的html代码
        result = parse_index_html(content)#解析索引页的相关内容

第五步:抓取并解析详细页信息
构造抓取详细页函数,这个和抓取索引页的函数几乎一样

#构造抓取详细页函数
def get_detail_html():
    try:
        response = requests.get(url)
        if response.status_code == 200:
            # print(response.apparent_encoding)
            response.encoding = 'utf8'
            return response.text
        return None
    except RequestException:
        return None

构造解析详细页函数,由于详细页的正文内容中有很多html标签,所以使用正则匹配比较复杂,这里使用BeautifulSoup相对而言更加适用。当然要先导入BeautifulSoup模块

from bs4 import BeautfulSoup
#构造解析详细页函数
def parse_detail_html(url):
    content = get_detail_html(url)
    if content:
        #构造bs对象,使用lxml解析方法,更加快速
        soup = BeautifulSoup(content,'lxml')
        results = soup.find('div',class_='imggin').get_text().strip()   

这样运行出来的话,结果在下方
这里写图片描述
我们可以看到,在content里面有很多\n(换行符),与\xa0(不间断空格符),我们需要将这些换行符等符号去除掉

results = soup.find('div',class_='imggin').get_text().strip().replace('\n','').replace('\xa0','')

运行结果如下,成功将换行符等去除
这里写图片描述
未写完,待续,先把暂时的代码放在下方(可以直接运行)

# -*- coding: utf-8 -*-
# @Time    : 2018/2/5 14:06
# @Author  : XueLei
# @Site    : 
# @File    : spider.py
# @Software: PyCharm
import re
import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException

#获取索引页,需要加一个timeout
def get_index_html(url):
    try:
        response = requests.get(url,timeout = 200)#我在这加了一个超时参数
        if response.status_code == 200:
            response.encoding = 'uft8'
            return response.text
        return None
    except RequestException as e:
        print(e)
        return None

#解析索引页,获取各文章的标题
def parse_index_html(content):
    #首页
    rooturl = 'http://news.aust.edu.cn/'
    # 匹配模式,S模式
    pattern = re.compile('<li id=.*?<font>(.*?)</font>.*?absmiddle.*?href="(.*?)" target="_blank">(.*?)</a>',re.S)
    results = re.findall(pattern,content)
    #遍历结果输出
    for result in results:
        publish_time = result[0]
        detail_url = rooturl+result[1]
        str1 = '../'#用于去除字符串中的../字符
        if detail_url:
            if str1 in detail_url:#如果字符串中有../
                detail_url = detail_url.replace('../','')
            paracontent = parse_detail_html(detail_url)#抓取并解析详细页信息
        title = result[2]
        data = {
            'time':publish_time,
            'url':detail_url,
            'title':title,
            'content':paracontent
        }
        print(data)

#获取详细页
def get_detail_html(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            # print(response.apparent_encoding)
            response.encoding = 'utf8'
            return response.text
        return None
    except RequestException as e:
        return e
#解析详细页,这里使用BeautiulSoup进行解析
def parse_detail_html(url):
    content = get_detail_html(url)
    if content:
        soup = BeautifulSoup(content,'lxml')
        results = soup.find('div',class_ = 'imggin').get_text().strip().replace('\n','').replace('\xa0','')
        return results
    return None


#去除图片
def remove_all_img():
    return None
#去除标签
def remove_all_label():
    return None
#获取每一页的url
def parse_all_url(content):
    #解析索引页面上的总页数
    page_pattern = re.compile('&nbsp;1/(.*?)&nbsp')
    pagenum = re.findall(page_pattern, content)
    page1 = int(pagenum[0])
    #获取每一页的url
    rooturl = 'http://news.aust.edu.cn/xxxw/'
    #循环构造url,并调用索引页解析函数
    for page in range(0,page1):
        if page ==0:
            wholeurl = 'http://news.aust.edu.cn/xxxw.htm'
        else :
            wholeurl = rooturl+str(page1-page)+'.htm'
        print(wholeurl,'这是第'+str(page+1)+"页")
        content = get_index_html(wholeurl)#获取每一各索引页的代码,用于找到url和标题
        parse_index_html(content)#解析每一索引页的代码


def main():
    url = 'http://news.aust.edu.cn/xxxw.htm'#首页面
    print(url)
    html = get_index_html(url)#这个只是解析总页数
    # print(html)
    try:
        parse_all_url(https://blog.csdn.net/html)#获取总页数,并构造每一页的url
    except RequestException as e:
        print(e)


if __name__ == '__main__':
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值