目录
一、聚焦爬虫
1.聚焦爬虫定义
聚焦爬虫就是爬取页面中指定的页面内容。
2.编码流程:
- 指定url
- 发起请求
- 获取响应数据
- 数据解析
- 持久化存储
二、数据解析
1.数据解析分类
①正则
②bs4
③xpath(重点)
2.数据解析原理概述:
解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储
- 1.进行指定标签的定位
- 2.标签或者标签对应的属性中存储的数据值进行提取(解析)
三、正则表达式解析案例
(正则的知识点自己补习一下,很简单)
可以应用在除python外的其他语言。
1.图片的简单爬取
需求:爬取糗事百科中的图片https://www.qiushibaike.com/
注意:爬取图片返回的是二进制文件,要用response.content
import requests
if __name__ == "__main__":
#如何爬取图片数据
url = 'https://pic.qiushibaike.com/system/pictures/12172/121721055/medium/9OSVY4ZSU4NN6T7V.jpg'
# 图片的网址是随便找了一张图片然后复制的图片地址
# content返回的是二进制形式的图片数据
# text(字符串) content(二进制)json() (对象)
img_data = requests.get(url=url).content
# 存到本地
with open('./qiutu.jpg','wb') as fp:
fp.write(img_data)
2.图片的进阶爬取
需求:爬取糗事百科中“热图”板块下所有的糗图图片
该代码爬取了一页
import requests
import re
import os
# 需求:爬取糗事百科中糗图板块下所有的糗图图片
if __name__ == "__main__":
# 创建一个文件夹,保存所有的图片
if not os.path.exists('./qiutuLibs'):
os.mkdir('./qiutuLibs')
url = 'https://www.qiushibaike.com/pic/'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
}
# 使用通用爬虫对url对应的一整张页面进行爬取
page_text = requests.get(url=url,headers=headers).text
# 使用聚焦爬虫将页面中所有的糗图进行解析/提取
# 设定正则表达式的规则
ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
img_src_list = re.findall(ex,page_text,re.S)
# print(img_src_list)
for src in img_src_list:
# 拼接出一个完整的图片url
src = 'https:'+src
# 请求到了图片的二进制数据
img_data = requests.get(url=src,headers=headers).content
# 生成图片名称
img_name = src.split('/')[-1]
# 图片存储的路径
imgPath = './qiutuLibs/'+img_name
with open(imgPath,'wb') as fp:
fp.write(img_data)
print(img_name,'下载成功!!!')
该代码爬取了所有页
import requests
import re
import os
# 需求:爬取糗事百科中糗图板块下所有的糗图图片
if __name__ == "__main__":
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
}
# 创建一个文件夹,保存所有的图片
if not os.path.exists('./qiutuLibs'):
os.mkdir('./qiutuLibs')
# 设置一个通用的url模板
url = 'https://www.qiushibaike.com/pic/page/%d/?s=5184961'
# pageNum = 2
for pageNum in range(1,3):
# 对应页码的url
new_url = format(url%pageNum)
# 使用通用爬虫对url对应的一整张页面进行爬取
page_text = requests.get(url=new_url,headers=headers).text
# 使用聚焦爬虫将页面中所有的糗图进行解析/提取
ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
img_src_list = re.findall(ex,page_text,re.S)
# print(img_src_list)
for src in img_src_list:
# 拼接出一个完整的图片url
src = 'https:'+src
# 请求到了图片的二进制数据
img_data = requests.get(url=src,headers=headers).content
# 生成图片名称
img_name = src.split('/')[-1]
# 图片存储的路径
imgPath = './qiutuLibs/'+img_name
with open(imgPath,'wb') as fp:
fp.write(img_data)
print(img_name,'下载成功!!!')
四、bs4解析案例
1.bs4介绍
①bs4是python独有的解析方式,只能用在python中。
②bs4数据解析的原理:
- 1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
- 2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
③两种对象实例化的方法
- 对象的实例化:
- 1.将本地的html文档中的数据加载到该对象中
fp = open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
- 2.将互联网上获取的页面源码加载到该对象中
page_text = response.text
soup = BeatifulSoup(page_text,'lxml')
④需要用pip安装bs4和lxml库,lxml是一种解析器
2.bs4的基本用法
①soup.tagName
tagName是任意的标签名,返回的是文档中第一次出现的tagName对应的标签,输出包括该标签在内的所有内容
②soup.find('tagName')
等同于soup.tagName
soup.find()还可以进行属性定位
③soup.find_all('tagName')
返回的是所有的tagName标签,是一个列表
④soup.select()
soup.select('某种选择器(id,class,标签...选择器)'),返回的是一个列表。
它可以根据层级关系进行定位。
soup.selecet('.class')
soup.select('#id')
soup.select('tagName')
⑤层级选择器:
- soup.select('.tang > ul > li > a'):>表示的是一个层级
- oup.select('.tang > ul a'):空格表示的多个层级
⑥获取标签之间的文本数据
- soup.a.text/string/get_text()
- text/get_text():可以获取某一个标签中所有的文本内容
- string:只可以获取该标签下面直系的文本内容
# 不能与find_all()配合使用,find和soup.tagName可以,因为这是单数
⑦获取标签中属性值
- soup.a['href']
3.代码实例
本文采用了一个简单的html文件,如果需要请在评论区下方留言!
from bs4 import BeautifulSoup
if __name__ == "__main__":
#将本地的html文档中的数据加载到该对象中
fp = open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
# 输出整个网页的源码
print(soup)
# 1.soup.tagName 返回的是html中第一次出现的tagName标签
print(soup.a)
print(soup.div)
# 2.soup.find('tagName'):等同于soup.tagName
print(soup.find('div')) # print(soup.div)
# 属性定位,涉及到class属性的时候,要用class_,因为class是关键字
print(soup.find('div',class_='song').string)
# 3.soup.find_all('tagName') 返回的是所有的tagName标签,是一个列表
print(soup.find_all('a'))
# 4.select选择器
print(soup.select('.tang'))
print(soup.select('.tang > ul a')[0]['href'])
# 把结果变成单数,就可以用text、get_text()和string
print(soup.select('.song > p')[0].text)
下面是一个实战案例
需求:爬取三国演义小说所有的章节标题和章节内容http://www.shicimingju.com/book/sanguoyanyi.html
需要注意的是,在爬取过程中我们可能遇到多个动态界面,每一次对动态界面访问都需要做request请求
import requests
from bs4 import BeautifulSoup
#需求:爬取三国演义小说所有的章节标题和章节内容http://www.shicimingju.com/book/sanguoyanyi.html
if __name__ == "__main__":
#对首页的页面数据进行爬取
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
}
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(url=url,headers=headers).text
# 在首页中解析出章节的标题和详情页的url
# 1.实例化BeautifulSoup对象,需要将页面源码数据加载到该对象中
soup = BeautifulSoup(page_text,'lxml')
# 解析章节标题和详情页的url
li_list = soup.select('.book-mulu > ul > li')
fp = open('./sanguo.txt','w',encoding='utf-8')
for li in li_list:
title = li.a.string
detail_url = 'http://www.shicimingju.com'+li.a['href']
# 对详情页发起请求,解析出章节内容
detail_page_text = requests.get(url=detail_url,headers=headers).text
# 解析出详情页中相关的章节内容
detail_soup = BeautifulSoup(detail_page_text,'lxml')
div_tag = detail_soup.find('div',class_='chapter_content')
# 解析到了章节的内容
content = div_tag.text
fp.write(title+':'+content+'\n')
print(title,'爬取成功!!!')
五、xpath解析案例
1.xpath介绍
①xpath解析:最常用且最便捷高效的一种解析方式。通用性。
②xpath解析原理:
- 1.实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
- 2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获。
③两种对象实例化的方法:
- 1.将本地的html文档中的源码数据加载到etree对象中: etree.parse(filePath)
- 2.可以将从互联网上获取的源码数据加载到该对象中 etree.HTML('page_text')
④需要用pip安装lxml库,lxml是一种解析器。from lxml import etree
2.xpath的基本用法
注意:xpath只能根据层级关系做标签定位,返回结果是一个列表。具体使用方法见下列代码。
① /:表示的是从根节点开始定位。表示的是一个层级。
② //:表示的是多个层级。可以表示从任意位置开始定位。
③属性定位:
通用格式:tag[@attrName="attrValue"]
举个例子://div[@class='song']
④索引定位:
通用格式:tag[@attrName="attrValue"]/tag[num]
举个例子://div[@class="song"]/p[3] 索引是从1开始的
⑤取文本:
- /text() 获取的是标签中直系的文本内容
- //text() 标签中非直系的文本内容(该标签下所有的文本内容,包括标签与其子标签中的文本内容)
⑥取属性:
通用格式:/@attrName
举个例子:img/@src
3.代码实例
from lxml import etree
if __name__ == "__main__":
#实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('test.html')
r = tree.xpath('/html/body/div') # 输出所有的div标签元素
r = tree.xpath('/html/body/div')[0] # 输出第一个div元素
r = tree.xpath('/html/body/div')
r = tree.xpath('//div') # 这两种方法等同于第一种
r = tree.xpath('//div[@class="song"]') # 根据class属性定位到具体的div
r = tree.xpath('//div[@class="tang"]//li[5]/a/text()')[0] # 输出标签中具体的文本内容,因为返回的结果是一个列表,而且列表中只有一个元素,所以要用[0]
r = tree.xpath('//li[7]//text()')[0] # 也可以用//直接定位标签
r = tree.xpath('//div[@class="tang"]//text()') # 输出该标签下的全部文本内容,结果是一个列表
r = tree.xpath('//div[@class="song"]/img/@src')[0] # 输出标签中的属性值
r = tree.xpath('//div[@class="tang"]//li[4]/a/@href')[0] # 这里的li[4]是索引值,从1开始
print(r)
下一篇文章我将编写3个实战案例来详细说明xpath的应用!