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节点下的。
这是树结构逻辑上的示意图:
在实际的html文件中,即为如下所示的地方(节点):
现在我们知道了超链接在html中所处的位置,可是该如何获取他们呢?一种方法是使用正则表达式把html当成字符串暴力处理,思路上就是类似if “<a + 别的啥字符>” in html的模式;另外一种是我们可以调用BeautifulSoup库强大的解析功能,让他帮我们定位,不过这样我们还需遵循如下的语法细节:
- BeautifulSoup()函数返回的是一个解析过的对象,相当于把你的html文本做了处理;
- 调用这个解析过的对象的find_all()方法,即返回一个该html中 所有的a节点组成的列表;
- 再对表中每一个节点调用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键对应的值,那我们只需要简单修改定位的函数即可。