Python 数据采集——爬取school news链接和标题


前言

用urlopen+Beautifulsoup完成一个学校新闻标题的爬取任务,具体要求如下:
(1)爬取地址 https://www.hist.edu.cn/index/sy/kyyw.htm。
(2)爬取新闻列表汇总的地址链接和题目信息。
(3)将爬取的信息存储到文件“xinwen.txt”中,一行显示一条信息,超链接和文本之间用逗号隔开。

  • 准备工作:
    • 爬取地址:https://www.hist.edu.cn/index/sy/kyyw.htm
    • 爬取数据:新闻的标题
    • 环境需求:安装扩展库 BeautifulSoup、urllib

一、扩展库的简要介绍

1、urllib 库

urllib 库是 python 内置的 HTTP 请求库,包括以下模块:

  • urllib.request  请求模块
  • urllib.error  异常处理模块
  • urllib.parse  url解析模块
  • urllib.robotparser  robots.txt解析模块

(1)urllib.request.urlopen()

urlopen 返回的 response 对象是 http.client.HTTPResponse 类型,主要包含 read()、readinfo()、getheader(name)、getheaders()、fileno() 等方法,我们需要用到的是 read() 方法,如下:

# 导入 urllib.request 模块
import urllib.request

# 解析我们给定的 url: https://www.hist.edu.cn/index/sy/kyyw.htm
# 即读取给定 url 的 html 代码 --> 输入 url, 输出 html
response = urllib.request.urlopen('https://www.hist.edu.cn/index/sy/kyyw.htm')
# 打印我们获取到的数据,并以 utf-8 形式进行解码
# 需要注意:修改 pycharm 的编码方式为 utf8, 否则会报错
print(response.read().decode('utf-8'))

2、BeautifulSoup 库

BeautifulSoup 是 Python 的一个第三方库,可以用来解析 html 数据,我们使用它的主要功能就是从网页抓取数据:

  • BeautifulSoup 提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能
  • BeautifulSoup 通过解析文档为用户提供需要抓取的数据
  • Beautiful Soup 自动将输入文档转换为 Unicode 编码,输出文档转换为 utf-8 编码

(1)BeautifulSoup()

BeautifulSoup 将复杂的 HTML 文档转换成一个复杂的树形结构,每个节点都是 Python对象。所有对象可以归纳为4种类型:

  • Tag:HTML 或者 XML 中的标签
  • NavigableString:标签中的文本内容(不包含标签)
  • BeautifulSoup:BeautifulSoup 对象表示一个文档的全部内容,支持遍历文档树和搜索文档树
  • Comment:HTML和XML中的注释
    我们可以利用 BeautifulSoup() 将上面读取到的 html 文档进行转换,如下:
    在这里插入图片描述

(2)find_all()

find_all() 为搜索文档树,搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件。返回值类型是 bs4.element.ResultSet,即返回的是多个该对象的集合,可以用for循环遍历,完整的语法如下:
find_all( name, attrs, recursive, string, **kwargs)
参数意义如下:

  • name:查找所有名字为 name 的 tag。
  • attr:tag的属性(即标签的属性)
  • string:搜索文档中string字符串的内容
  • recursive: 调用 tag 的 find_all() 方法时,BeautifulSoup 会检索当前 tag 的所有子孙节点;如果只想搜索tag的直接子节点,可以使用参数 recursive=False

上面我们已转换 html 文档,接下来我们使用 find_all() 获取我们想要的数据,但在此之前,我们需要知道我们搜索数据的条件是什么?这需要我们通过调试网页得知,具体如下:

  • 通过调试网页我们知道,新闻标题所在元素全部包含在lib标签下,外层被 div 标签所包裹, 该 div 标签具有属性 class=“list-main-warp”,因此我们可以使用 find_all() 获取名字为 div 且属性为 class="list-main-warp"的 tag 数据,然后再使用 find_all() 从已获取的div数据里获取名字为 li 的 tag 数据,然后打印输出其中的标题title
    在这里插入图片描述

代码实现:

# 获取转换后的html文档里属性class=list-main-warp
divs = soup.find_all('div',{'class','list-main-warp'})
# 从已获取的 div 标签的内容里获取 li 标签的内容
lis = divs[0].find_all('li')
# 遍历获取到的 lis 列表,并从中抓取链接和标题
for li in lis:
    # print(li.find_all('a')[0].get('href'))
    print(li.find_all('a')[0].get('title'))

输出结果:
在这里插入图片描述

有了以上基础之后,最后完成第三步,将获取到的信息写入文件。

# 创建文件并写入信息
with open('xinwen.txt','w') as fp:
    for li in lis:
        url2 = li.find_all('a')[0].get('href')
        # parse.urljoin(former,later)将相对的地址组合成一个绝对地址url,对于输入没有限制,开头必须是http://,否则将不组合前面。用former的域名拼接later的路径,如果later有域名,则进行忽略
        url2 = parse.urljoin(url,url2)
        title = li.find_all('a')[0].get('title')
        fp.write(url + ',' + title +'\n')

二、bug及解决方法

在运行时报错You provided Unicode markup but also provided a value for from_encoding
在这里插入图片描述
原因是在用BeautifulSoup()将html文档进行转换时规定了编码,python3缺省的编码是unicode, 再在from_encoding设置为utf8, 会被忽视掉,删掉【from_encoding=“utf-8”】就又可以完美运行啦!

三、完整代码

import urllib.request
from bs4 import BeautifulSoup
from urllib import parse

# 解析我们给定的 url: https://www.hist.edu.cn/index/sy/kyyw.htm
# 即读取给定 url 的 html 代码 --> 输入 url, 输出 html
url = "https://www.hist.edu.cn/index/sy/kyyw.htm"
response = urllib.request.urlopen(url)
# 打印我们获取到的数据,并以 utf-8 形式进行解码
# 需要注意:修改 pycharm 的编码方式为 utf8, 否则会报错
content = response.read().decode('utf-8')

# 利用 BeautifulSoup()将上面读取到的html文档进行转换
# soup = BeautifulSoup(content,'html.parser',from_encoding='utf-8')
# ps:python3缺省的编码是unicode, 再在from_encoding设置为utf8, 会被忽视掉,去掉【from_encoding="utf-8"】就不会报错了
soup = BeautifulSoup(content,'html.parser')


# 获取转换后的html文档里属性class=list-main-warp
divs = soup.find_all('div',{'class','list-main-warp'})
# 从已获取的 div 标签的内容里获取 li 标签的内容
lis = divs[0].find_all('li')
# 遍历获取到的 lis 列表,并从中抓取链接和标题
# for li in lis:
#     print(li.find_all('a')[0].get('href'))
#     print(li.find_all('a')[0].get('title'))

# 创建文件并写入信息
with open('xinwen.txt','w') as fp:
    for li in lis:
        url2 = li.find_all('a')[0].get('href')
        # parse.urljoin(former,later)将相对的地址组合成一个绝对地址url,对于输入没有限制,开头必须是http://,否则将不组合前面。用former的域名拼接later的路径,如果later有域名,则进行忽略
        url2 = parse.urljoin(url,url2)
        title = li.find_all('a')[0].get('title')
        fp.write(url + ',' + title +'\n')

版权声明:本文参考了CSDN博主「安悦悦ya」的原创文章。
原文链接:https://blog.csdn.net/pola_/article/details/121316947

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值