python对网页进行爬虫
基于BeautifulSoup的爬虫—源码
"""
基于BeautifulSoup的爬虫
###?一、BeautifulSoup简介
1.?Beautiful?Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
2.?Beautiful?Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful
3.?Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
4.?Beautiful?Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
5.?BS基于DOM结构进行页面内容解析,当开始解析时,会将整个页面的DOM树保存于内存中,进而实现查找。
解析器:
1.?Python标准库?BeautifulSoup(markup,?"html.parser")?-?Python的内置标准库,执行速度适中,文档容错能力强
2.?lxml?HTML解析器?BeautifulSoup(markup,?"lxml")?-?速度快,文档容错能力强,需要安装C语言库
3.?lxml?XML解析器?BeautifulSoup(markup,?"xml")?-?速度快,唯一支持XML的解析器,需要安装C语言库
4.?html5lib?BeautifulSoup(markup,?"html5lib")?-?最好的容错性,以浏览器的方式解析文档,生成HTML5格式的文档,速度慢,不依赖外部扩展
###?二、具体代码使用
"""
from?bs4?import?BeautifulSoup
import?requests
resp?=?requests.get('https://www.cnblogs.com/leyinsec')
#?初始化解析器
html?=?BeautifulSoup(resp.text,?'lxml')
#?查找页面元素,根据标签层次进行查找
#?print(html.head.title)
#?print(html.head.title.string)
#?print(html.div)
#?print(html.div.div)
#?查找页面元素的通用方法,find_all,select
#?查找页面所有超链接
def?html_href():
????links?=?html.find_all('a')
????for?link?in?links:
????????try:
????????????print(link['href'])
????????except?KeyError:
????????????print("No?href?attribute?found?for?this?tag")
#?查找页面图片
def?html_images():
????images?=?html.find_all('img')
????for?image?in?images:
????????print(image['src'])
"""
#?根据id或calss等属性查找
keyword?=?html.find_all(id='keyword')
print(keyword)
print(keyword['placeholder'])
#?根据title查找
titles?=?html.find_all(class_='title')
for?title?in?titles:
????print(title)
????print(title.find('a'))
#?根据text查找
title?=?html.find(text='leyinsec')
print(title.parent)
#?根据xpath的风格进行查找?//[@class='title'?and/or?@id=1]
titles?=?html.find_all('div',?{'class':?'title'})
for?title?in?titles:
????print(title)
????
#?css选择器
titles?=?html.select('div.title')
for?title?in?titles:
????print(title)
????
#?css选择器查找id
keyword?=?html.select('#keyword')
try:
????print(keyword['placeholder'])
except?TypeError:
????print("No?keyword?attribute?found?for?this?tag")
#?列表查找
lis?=?html.select('ul?li')
print(lis)
"""
if?__name__?==?'__main__':
????html_images()
基于BeautifulSoup的爬虫—源码解析
这段代码是一个基于BeautifulSoup库的简单爬虫示例,用于从指定的网页中提取超链接和图片链接。下面是对代码的详细分析:
导入库
from?bs4?import?BeautifulSoup
import?requests
这两行代码导入了编写爬虫所需的两个库:BeautifulSoup
用于解析HTML文档,requests
用于发送HTTP请求。
发送HTTP请求
resp?=?requests.get('https://www.cnblogs.com/leyinsec')
这行代码使用requests
库向指定的URL发送GET请求,并将响应存储在变量resp
中。
解析HTML文档
html?=?BeautifulSoup(resp.text,?'lxml')
这行代码使用BeautifulSoup解析HTTP响应中的文本内容。这里使用了’lxml’作为解析器,因为它通常比Python内置的解析器更快且具有更好的容错性。
定义查找页面元素的函数
查找所有超链接
def?html_href():
????links?=?html.find_all('a')
????for?link?in?links:
????????try:
????????????print(link['href'])
????????except?KeyError:
????????????print("No?href?attribute?found?for?this?tag")
这个函数查找HTML文档中所有的<a>
标签,并尝试打印出每个链接的href
属性。如果某个<a>
标签没有href
属性,则会捕获KeyError
异常并打印一条消息。
查找所有图片
def?html_images():
????images?=?html.find_all('img')
????for?image?in?images:
????????print(image['src'])
这个函数查找HTML文档中所有的<img>
标签,并打印出每个图片的src
属性。
根据属性查找元素
keyword?=?html.find_all(id='keyword')
print(keyword)
print(keyword['placeholder'])
这段代码尝试查找具有特定id
属性的元素,并打印出该元素及其placeholder
属性。但是这里有一个错误:keyword
是一个列表,所以不能直接使用keyword['placeholder']
。应该遍历列表并分别访问每个元素的属性。
根据类名查找元素
titles?=?html.find_all(class_='title')
for?title?in?titles:
????print(title)
????print(title.find('a'))
这段代码查找所有具有title
类的元素,并打印出这些元素及其内部包含的<a>
标签。
根据文本查找元素
title?=?html.find(text='leyinsec')
print(title.parent)
这段代码查找文本内容为leyinsec
的元素,并打印出该元素的父元素。
使用CSS选择器查找元素
titles?=?html.select('div.title')
for?title?in?titles:
????print(title)
这段代码使用CSS选择器语法查找所有具有title
类的<div>
元素,并打印它们。
查找具有特定ID的元素
keyword?=?html.select('#keyword')
try:
????print(keyword['placeholder'])
except?TypeError:
????print("No?keyword?attribute?found?for?this?tag")
这段代码试图查找具有特定ID的元素,并打印其placeholder
属性。但是这里同样有一个错误:keyword
是一个列表,所以不能直接使用keyword['placeholder']
。应该遍历列表并分别访问每个元素的属性。
列表查找
lis?=?html.select('ul?li')
print(lis)
这段代码查找所有在<ul>
标签内的<li>
元素,并打印出这个列表。
主函数调用
if?__name__?==?'__main__':
????html_images()
这段代码确保当脚本作为主程序运行时,调用html_images()
函数来执行图片链接的查找和打印。
总结
这段代码展示了如何使用BeautifulSoup库来解析HTML文档,并通过不同的方法查找和提取页面元素。需要注意的是,代码中有一些错误需要修正,特别是在处理查找结果为列表的情况时。此外,代码中没有处理网络请求可能出现的异常,例如连接错误或HTTP错误状态码。在实际应用中,应该添加适当的异常处理来提高代码的健壮性。
基于正则表达式的爬虫—源码
"""
基于正则表达式的爬虫
以下是提取的文章内容:
###?一、爬虫简介
1.?**搜索引擎**:百度,谷歌,企业内部的知识库,某些项目专项数据爬取,专业的数据爬取。
2.?**互联网**:
???-?公网(不需要授权的情况就可以浏览的内容,搜索引擎的重点)
???-?深网(需要授权才能使用的内容)
???-?暗网(非正式渠道,无法使用常规手段访问)
3.?**爬取互联网的公开信息**,但是正常情况下,也需要遵守一个规则:robots协议:[https://www.baidu.com/robots.txt](https://www.baidu.com/robots.txt)(君子协议)
###?二、基本原理
1.?**所有和网页,均是HTML**:
???-?HTML首先是一个大的字符串,可以按照字符串处理的方式对响应进行解析处理。
???-?其次,HTML本身也是一门标记语言,与XML是同宗同源,所以可以使用DOM对其文本进行处理。
2.?**所有的爬虫,核心基于超链接**,进而实现网站和网页的跳转。给我一个网站,爬遍全世界。
3.?**如果要实现一个整站爬取**,首先要收集到站内所有网址,并且将重复网址去重,开始爬取内容并保存在本地数据库,进行实现后续目标。
###?三、正则表达式实现
"""
import?re
import?time
import?requests
def?download_page():
????resp?=?requests.get('https://www.cnblogs.com/leyinsec')
????#?解析网页所有超链接
????links?=?re.findall('<a?href="(.+?)"',?resp.text)
????for?link?in?links:
????????#?排除无用链接
????????if?'postid'?in?link?or?'archive'?in?link:
????????????continue
????????elif?link.startswith('javascript'):
????????????continue
????????#?将页面文件保存在本地
????????resp?=?requests.get(link)
????????resp.encoding?=?'utf-8'
????????filename?=?link.split('/')[-1]?+?time.strftime("_%Y%m%d_%H%M%S")?+?'.html'
????????with?open(f'page/leyinsec博客园/{filename}',?'w',?encoding='utf-8')?as?file:
????????????file.write(resp.text)
def?download_images():
????resp?=?requests.get('https://www.cnblogs.com/leyinsec')
????images?=?re.findall('<img?src="(.+?)"',?resp.text)
????for?image?in?images:
????????if?image.startswith('/'):
????????????image?=?'https://www.cnblogs.com/leyinsec'?+?image
????#?下载图片
????????resp?=?requests.get(image)
????????filename?=?time.strftime("_%Y%m%d_%H%M%S")?+?image.split('/')[-1]
????????with?open('page/leyinsec博客园/photos/'?+?filename,?'wb')?as?file:
????????????file.write(resp.content)
if?__name__?==?'__main__':
????download_page()
????download_images()
基于正则表达式的爬虫—源码解析
这段代码是一个简单的基于正则表达式的爬虫,用于从指定的网页中提取超链接和图片链接,并将它们保存到本地文件系统中。下面是对代码的详细分析:
导入库
import?re
import?time
import?requests
这三行代码导入了编写爬虫所需的三个库:re
用于处理正则表达式,time
用于处理时间相关的功能,requests
用于发送HTTP请求。
下载网页内容的函数
def?download_page():
????resp?=?requests.get('https://www.cnblogs.com/leyinsec')
????#?解析网页所有超链接
????links?=?re.findall('<a?href="(.+?)"',?resp.text)
????for?link?in?links:
????????#?排除无用链接
????????if?'postid'?in?link?or?'archive'?in?link:
????????????continue
????????elif?link.startswith('javascript'):
????????????continue
????????#?将页面文件保存在本地
????????resp?=?requests.get(link)
????????resp.encoding?=?'utf-8'
????????filename?=?link.split('/')[-1]?+?time.strftime("_%Y%m%d_%H%M%S")?+?'.html'
????????with?open(f'page/leyin?sec博客园/{filename}',?'w',?encoding='utf-8')?as?file:
????????????file.write(resp.text)
这个函数首先发送一个GET请求到指定的URL,然后使用正则表达式查找所有的超链接。对于每个找到的链接,它会检查链接是否包含特定的字符串(如’postid’或’archive’),或者是否以’javascript’开头,如果是,则跳过该链接。对于其他链接,它会发送另一个GET请求以获取网页内容,并将其保存到本地文件系统中,文件名包含时间戳以确保唯一性。
下载图片的函数
def?download_images():
????resp?=?requests.get('https://www.cnblogs.com/leyinsec')
????images?=?re.findall('<img?src="(.+?)"',?resp.text)
????for?image?in?images:
????????if?image.startswith('/'):
????????????image?=?'https://www.cnblogs.com/leyinsec'?+?image
????#?下载图片
????????resp?=?requests.get(image)
????????filename?=?time.strftime("_%Y%m%d_%H%M%S")?+?image.split('/')[-1]
????????with?open('page/leyinsec博客园/photos/'?+?filename,?'wb')?for?file:
????????????file.write(resp.content)
这个函数的工作方式与download_page
函数类似,但是它查找的是<img>
标签中的src
属性。对于每个找到的图片链接,如果链接是相对路径(以’/'开头),它会将其转换为绝对路径。然后,它会发送GET请求以下载图片,并将其保存到本地文件系统中,文件名同样包含时间戳。
主函数调用
if?__name__?==?'__main__':
????download_page()
????download_images()
这段代码确保当脚本作为主程序运行时,调用download_page()
和download_images()
函数来执行网页内容和图片的下载。
注意事项和潜在问题
-
硬编码的URL:代码中硬编码了要爬取的网站URL,这限制了脚本的通用性。
-
缺乏异常处理:代码中没有处理网络请求可能出现的异常,例如连接错误或HTTP错误状态码。
-
缺乏robots.txt检查:代码没有检查目标网站的robots.txt文件,这可能会违反网站的爬虫政策。
-
文件路径错误:在
download_page
函数中,文件路径字符串有一个小错误,leyin?sec
应该是leyinsec
。 -
重复下载:代码没有实现去重逻辑,可能会下载重复的网页或图片。
-
编码问题:代码假设所有网页和图片都可以使用UTF-8编码,这可能不总是正确的。
-
性能问题:对于大型网站,这种简单的递归下载方法可能会导致大量的并发请求,从而对目标服务器造成压力。
总结
这段代码展示了如何使用正则表达式和requests
库来爬取网页内容和图片,并将它们保存到本地。然而,代码中存在一些问题和潜在的改进空间,特别是在异常处理、遵守robots.txt规则、错误处理和性能方面。在实际应用中,应该考虑这些问题,并采取相应的措施来提高代码的健壮性和效率。