一、基础知识
1、常见的数据解析方式:
-
正则:既可以在python中使用,也可以在其他语言中使用;
-
bs4:只可以在python语言中使用;
-
实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中;
-
通过调用BeautifulSoup对象中的相关属性或者方法进行标签定位和数据提取;
需要安装两个三方模块:
-
pip install bs4 (BeautifulSoup对象存在于bs4这个模块中)
-
pip install lxml (解析器)
-
xpath(重点):通用性最强;
2、数据解析的原理:
-
聚焦爬虫解析的局部文本内容,都会在标签之间或者标签对应的属性中进行存储;
-
进行指定标签的定位;
-
标签或标签对应的属性值中存取的数据值进行提取(解析);
3、聚焦爬虫相对于通用爬虫的编码流程会多增加一条:
-
指定url
-
发起请求
-
获取响应数据
-
数据解析
-
持久化存储
4、xpath解析:最常用且最便捷高效得一种解析方式,通用性也好:
-
xpath解析原理:
-
实例化一个etree对象,需要将被解析得页面源码数据加载到该对象中;
-
调用etree对象中得xpath方法,结合xpath表达式实现表得定位+内容得捕获;
-
环境的安装:
-
pip install lxml
-
如何实例化一个etree对象:
-
将本地的html文档中的源码数据加载到etree对象中:etree.parse(filePath)
-
将互联网上获取到的源码数据加载到etree对象中:etree.HTML(page_text)
-
使用的时候:et.xpath('xpath表达式')
-
xpath表达式:
-
/:标识从根节点开始定位,且单/表示一个层级;
-
//:表示多个层级,可以表示从任意位置开始定位;
-
属性定位:tag[@attrName='attrValue'],例如://div[@class='song'];
-
索引定位:例如://div[@class='song']/p[3],注意:这里的索引是从1开始的;
-
获取文本内容:
-
/text() :获取的是标签中直系的文本内容,返回值为数组,我们一般取索引为[0]位置的值;
-
//text() :获取的是标签中所有的文本内容,包括非直系的,返回值为数组;
-
获取属性值:
-
/@attrName : 获取某个标签的属性值,例如://div[@class='song']/img/@src;
-
xpath补充:xpath表达式可以使用 | 或连接符进行拼接:
all_list = tree.xpath('//div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
# 通过这样的可拼接特性,xpath表达式就变得更加的强大!
二、实战小功能案例 — 58同城二手车图片(正则解析)
1、打开网站进行分析:https://sh.58.com/ershouche/
我们可以得到如下结论:
所有的图片都被包裹在一个class = "info_pic" 的<img>标签中;
上面定位出来的img标签中的 data-original 属性就是图片缩略图的url:
如果将上面的缩略图url进行截取,得到的就是大图的url:
2、有了上面的核心分析结论后,我们就直接开始coding编码吧:
import requests
import re
import os
if __name__ == '__main__':
# 先准备一个文件夹,保存所有的图片
if not os.path.exists('./output/58pics'):
os.mkdir('./output/58pics')
# 准备UA伪装
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
}
# 设置一个通配的url模板字符串
temp_url = 'https://sh.58.com/ershouche/pn%d/'
# 提前分析定义好正则表达式(使用.*?进行通配,\进行转义,(.*?)中的内容将是我们最终获得到的内容)
ex = '<div class="info--pics">.*?data-original="(.*?)\?.*?</div>'
# 正式干活,虽然页面显示有70页,但是我们只测试个5页即可
for pageNum in range(1, 6):
real_url = temp_url % pageNum
response_text = requests.get(real_url, headers=headers).text
img_url_list = re.findall(ex, response_text, re.S)
print(img_url_list, "图片列表...")
# 下载img_url对应的图片到本地
for img_url in img_url_list:
# 取/分割的最后一段为图片名称,确保不重复
img_name = str(img_url).split("/")[-1]
# 发起请求,获得的数据为二进制数据,所以得用.content获取
img_data = requests.get(img_url, headers=headers).content
# 将img_data数据存储到文件,注意mode为‘wb’,因为存储的是二进制数据,且不需要指定encoding
with open("./output/58pics/" + img_name, 'wb') as fp:
fp.write(img_data)
print(img_name, "下载成功...")
3、我们运行程序进行测试:

查看最终下载到的图片:

非常Nice! (#^.^#)
三、实战小功能案例 — 爬取《三国演义》所有章节标题和内容(bs4解析)
1、安装bs4、lxml模块:
# 如果报错的话,检查是不是开着vpn pip install bs4 pip install lxml
2、浏览器访问网站:https://www.shicimingju.com/book/sanguoyanyi.html

爬取思路:
-
首先访问首页,可以轻松获得所有的章节标题:https://www.shicimingju.com/book/sanguoyanyi.html
-
每一个章节都能拼接出每一章节详情页的url:https://www.shicimingju.com/book/sanguoyanyi/1.html
-
再从每一个详情页中解析出正文内容;
-
页面标签的层级关系,class = 'book-mulu' 的div标签 > ul >li > a标签
3、直接开始coding编码:
import requests
from bs4 import BeautifulSoup
import os
if __name__ == '__main__':
if not os.path.exists('./output/sanguo'):
os.mkdir('./output/sanguo')
# 准备UA伪装
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
}
# 设置url模板
index_url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
detail_base_url = 'https://www.shicimingju.com'
# 开始干活
# 1、获取首页源码
index_response = requests.get(index_url, headers=headers)
index_response.encoding = 'utf-8'
index_text = index_response.text
# 实例化BeautifulSoup对象
index_soup = BeautifulSoup(index_text, 'lxml')
# 解析出章节标题和详情页的url
li_list = index_soup.select('.book-mulu > ul > li')
# 2、提前准备好一个文件,这样每一次直接追加即可:
fp = open('./output/sanguo/三国演义.txt', 'w', encoding='utf-8')
# 3、处理首页的soup元素,并发起详情页的请求
for li in li_list:
# 直接a.string获取a标签中的文本作为title
title = li.a.string
detail_url = detail_base_url + li.a['href']
# 对详情页发起请求,并解析出章节内容
detail_response = requests.get(detail_url, headers=headers)
detail_response.encoding = 'utf-8'
detail_text = detail_response.text
detail_soup = BeautifulSoup(detail_text, 'lxml')
content_tag = detail_soup.find('div', class_='chapter_content')
# 将title和正文全部写入到提前准备好的fp
fp.write(title + ':\n' + content_tag.text + '\n')
print(title, ':章节下载完成')
4、运行程序,测试结果:

查看《三国演义.txt》文本文件:

非常Nice,没毛病,老铁!o(* ̄︶ ̄*)o
四、实战小功能案例 — 4K图片解析下载(解决编码乱码用例)(xpath解析)
1、打开网址对页面结构进行分析:https://pic.netbian.com/4kmeinv/

所有的图片都被包裹在 //ul[class=clearfix] -> li -> a -> img标签中;
src属性中是图片的url链接,alt中是图片的名称;
2、话不多说,直接coding编码:
import requests
from lxml import etree
import os
if __name__ == '__main__':
if not os.path.exists('./output/4kpics'):
os.mkdir('./output/4kpics')
# 准备UA伪装
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
}
url = 'https://pic.netbian.com/4kmeinv/'
base_url = 'https://pic.netbian.com/'
# 开始干活
response = requests.get(url, headers=headers)
resp_text = response.text
# 获得etree对象
et = etree.HTML(resp_text)
li_list = et.xpath('//ul[@class="clearfix"]/li')
for li in li_list:
img_url = li.xpath('./a/img/@src')[0]
img_name = li.xpath('./a/img/@alt')[0]
# 由于纯在乱码的问题,我们可以使用一个很常用的方式进行重新编码解码
new_img_name = img_name.encode('iso-8859-1').decode('gbk')
img_data = requests.get(base_url+img_url, headers=headers).content
with open('./output/4kpics/'+new_img_name+'.jpg', 'wb') as fp:
fp.write(img_data)
print(new_img_name, "下载完成....")
3、测试,查看结果:

看下载好的图片:

Very Nice! (●'◡'●)




