Python爬虫-获得某一链接下的所有超链接

Python爬虫-获得某一链接下的所有超链接

用到的库

Beautifulsoup4、requests、re模块

import requests as rq
from bs4 import BeautifulSoup as bs
import re

具体实现:

1. 获得某页面的html内容

要获得某一个页面的html,没什么好说,直接调用request库吧!

要注意的是这里request.get()返回的是一个response类型,但是这个类其实是包括了我们需要的html信息的,只需要调用该类的text()方法即可返回网页的源代码。

def gethtml(rooturl, encoding="utf-8"):
    # 默认解码方式utf-8
    response = rq.get(rooturl)
    response.encoding = encoding
    html = response.text
    return html  # 返回链接的html内容

3.获得某html下的所有超链接

现在我们获得了某一个网址的源代码,学过html或者数据结构的同学都很容易知道,我们要找的超链接一般是藏在DOM树的a节点下的。

这是树结构逻辑上的示意图:
图片来自:https://www.w3school.com.cn/htmldom/dom_nodes.asp
在实际的html文件中,即为如下所示的地方(节点):
在这里插入图片描述
现在我们知道了超链接在html中所处的位置,可是该如何获取他们呢?一种方法是使用正则表达式把html当成字符串暴力处理,思路上就是类似if “<a + 别的啥字符>” in html的模式;另外一种是我们可以调用BeautifulSoup库强大的解析功能,让他帮我们定位,不过这样我们还需遵循如下的语法细节:

  1. BeautifulSoup()函数返回的是一个解析过的对象,相当于把你的html文本做了处理;
  2. 调用这个解析过的对象的find_all()方法,即返回一个该html中 所有的a节点组成的列表;
  3. 再对表中每一个节点调用get()方法,获得该节点下"herf"标签(键)的所有值,也就是我们的要找“http://”打头的超链接了;
def getherf(html):
    # 使用BeautifulSoup函数解析传入的html
    soup = bs(html, features="lxml")
    allnode_of_a = soup.find_all("a")
    result = [_.get("href") for _ in allnode_of_a]
    # print(result)
    return result

4.筛除结果中非链接的元素

实际应用过程中我们会发现,有些herf的值并不是我们要找的超链接,而是其他的文本:
在这里插入图片描述
这就导致获取到的result中还包含一些奇怪的东西:
在这里插入图片描述

如此,我们就需要对获得的结果进行一次筛查,排除不需要的元素并保留链接,那这里比较直接的方法就是使用前面提到的正则化,简单来说,"http://"打头的就留下,否则就删除:

  • re.match(pattern, string)可以接收两个参数,前者是模式后者是待匹配字符,形象地理解为:通过re.match(长得高,一堆女的)来找我的理想型女朋友,那得先有要求才能相亲啊
  • urlptn即匹配模式,单独的“.”表示除\n外的所有单字符,(.+)就表示http://后面的单字符重复1次或多次;
  • 但是re.macth()返回的并不直接是我们需要的链接,倘若匹配成功,我们需要对获得的对象(长得高的更可能成为对象 (大雾))调用group()方法来获得字符串,即为链接;
  • 这么做的问题是:若匹配失败,返回的none也在表中了,但是none没有group方法,程序就会报错,那我们只需要在逐个调用group前筛除所有none就好了,我这里采用的是while循环的办法。
def filterurl(result):
    # result参数:get到的所有a标签内herf的内容
    # 对列表中每个元素进行筛选
    urlptn = r"http://(.+)"  # 匹配模式: 所有http://开头的链接
    urls = [re.match(urlptn, str(_)) for _ in result]  # 正则筛选
    # print(urls)
    while None in urls:
        urls.remove(None)  # 移除表中空元素
    urls = [_.group() for _ in urls]  # group方法获得re.match()返回值中的字符
    # print(urls)
    return urls

主程序

html = gethtml("http://huxi.cqu.edu.cn/")
result = getherf(html)
urls = filterurl(result)
print(urls)

大功告成!

在这里插入图片描述
这样一来我们就完成了对某一网址的所有超链接的提取,后续再顺藤摸瓜来爬取被指向的网站就容易很多了。当然对某一网站的其他内容(图片,音频,电子书等)的提取也大同小异,例如有的网站的图片链接是储存在img节点下的,即img节点的src键对应的值,那我们只需要简单修改定位的函数即可。

  • 13
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值