1. bs4解析
环境安装:
- pip install lxml #解析器
- pip install bs4
bs4解析原理:
- 实例化一个BeautifulSoup的对象,且将待解析的页面源码数据加载到该对象中
- 调用BeautifulSoup对象中相关方法或者属性进行标签定位和文本数据的提取
BeautifulSoup对象的实例化:
- BeautifulSoup(fp,‘lxml’):用来将本地存储的html文档中的数据进行解析
- BeautifulSoup(page_text,’lxml‘):用来将互联网上请求到的页面源码数据进行解析
标签定位:
- soup.tagName:只可以定位到第一次出现的tagName标签
- soup.find(‘tagName’,attrName=‘value’):属性定位
- soup.find_all:跟find一样用作属性定位,只不过findAll返回的是列表
- soup.select(‘选择器’):选择器定位
- 类选择器
- id选择器
- 层级选择
- 大于号:表示一个层级
- 空格:表示多个层级
取数据:
- .text:返回的是该标签下所有的文本内容
- .string:返回的是该标签直系的文本内容
取属性:
- tag[‘attrName’]
2. bs4实例:爬取站长之家高清日出图片
url:http://sc.chinaz.com/tupian/richutupian.html
需求:
- 将首页所有图片都爬取下来
首页:
分析:
站长素材高清图片下载用到了图片懒加载,该方法广泛应用在了一些图片的网站中。
该方法的特点是只有当图片被显示在浏览器可视化范围之内才会将img的伪属性变成真正的属性。如果是requests发起的请求,requests请求是没有可视化范围,因此我们一定要解析的是img伪属性的属性值(图片地址)。
真正的属性:src
伪属性(需要解析的):src2
程序代码:
import requests
import os
from bs4 import BeautifulSoup
dirName = '日出图片'
if not os.path.exists(dirName):
os.mkdir(dirName)
url = 'http://sc.chinaz.com/tupian/richutupian.html'
headers = {
'User_Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
r = requests.get(url=url, headers=headers)
r.encoding = r.apparent_encoding
page_text = r.text
soup = BeautifulSoup(page_text, 'lxml')
img_list = soup.select('div > div > a > img')
for img in img_list:
title = img['alt'] + '.jpg'
img_url = img['src2']
img_data = requests.get(url=img_url, headers=headers).content
img_path = dirName + '/' + title
with open(img_path, 'wb') as fp:
fp.write(img_data)
print(title, '保存成功!')
运行结果:
3. xpath解析
环境安装:
- pip install lxml
解析原理:html标签是以树状的形式进行展示
- 实例化一个etree的对象,且将待解析的页面源码数据加载到该对象中
- 调用etree对象的xpath方法结合着不同的xpath表达式实现标签的定位和数据提取
实例化etree对象:
- etree.parse(‘filename’):将本地html文档加载到该对象中
- etree.HTML(page_text):网站获取的页面数据加载到该对象
标签定位:
- 最左侧的/:如果xpath表达式最左侧是以/开头则表示该xpath表达式一定要从根标签开始定位指定标签(忽略)
- 非最左侧的/:表示一个层级
- 非左侧的//:表示多个层级
- 最左侧的//:xpath表达式可以从任意位置进行标签定位
- 属性定位:tagName[@attrName=“value”]
- 索引定位:tag[index]:索引是从1开始
- 模糊匹配:
- //div[contains(@class, “ng”)]
- //div[starts-with(@class, “ta”)]
取文本:
- /text():直系文本内容
- //text():所有的文本内容
取属性:
- /@attrName
4. xpath实例:爬取站长之家简历模板
url:http://sc.chinaz.com/jianli/free.html
需求:
- 将首页中每一个模板的压缩包都下载下来
- 总共爬取前5页的模板
首页:
详情页:
分析:
从首页中解析出简历名称和详情页的url,从详情页中解析出下载地址,向这个链接发起请求,获取响应的content即为模板的压缩包,对其做持久化存储。
程序代码:
import requests
import os
from lxml import etree
dirName = '简历模板'
if not os.path.exists(dirName):
os.mkdir(dirName)
url = 'http://sc.chinaz.com/jianli/free_%d.html'
headers = {
'User_Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
for page in range(1, 5):
if page == 1:
new_url = 'http://sc.chinaz.com/jianli/free.html'
else:
new_url = format(url, page)
r = requests.get(url=new_url, headers=headers)
r.encoding = r.apparent_encoding
page_text = r.text
tree = etree.HTML(page_text)
a_list = tree.xpath('//div[@id="main"]//div/a')
for a in a_list:
title = a.xpath('./img/@alt')[0] + '.zip'
detail_url = a.xpath('./@href')[0]
r = requests.get(url=detail_url, headers=headers)
r.encoding = r.apparent_encoding
page_text_detail = r.text
tree = etree.HTML(page_text_detail)
zip_url = tree.xpath('//ul[@class="clearfix"]/li[4]/a/@href')[0]
zip_data = requests.get(url=zip_url, headers=headers).content
zip_path = dirName + '/' + title
with open(zip_path, 'wb') as fp:
fp.write(zip_data)
print(title, '保存成功!')