- 概念:就是将一组数据中的局部数据进行提取
- 作用:使用来实现聚焦爬虫
- 问题:html展现的数据可以存储在哪里?
- 标签之中
- 属性中
1、标签定位
2、取文本或者取属性
需求:http://duanziwang.com/category/%E6%90%9E%E7%AC%91%E5%9B%BE/,将该网站中的图片数据进行爬取
如何对图片(二进制)数据进行爬取
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
url = 'http://duanziwang.com/usr/uploads/2019/02/3334500855.jpg'
pic_data = requests.get(url=url,headers=headers).content #content返回的是二进制类型的响应数据
with open('1.jpg','wb') as fp:
fp.write(pic_data)
#方法2:urllib就是一个低版本的requests
import urllib
url = 'http://duanziwang.com/usr/uploads/2019/02/3334500855.jpg'
urllib.request.urlretrieve(url=url,filename='./2.jpg')
('./2.jpg', <http.client.HTTPMessage at 0x27aab4fde80>)
- 两种图片爬取的方法的区别是什么?
- 方法1可以进行UA伪装,方法2不行
- 抓包工具中response中显示的页面源码和开发者工具的Element选项卡显示的页面源码的区别是什么?
- Element:显示的页面源码内容是当前网页加载完毕后对应的所有数据(包含动态加载的数据)
- response:显示的内容仅仅是当前一个请求请求到的数据(不包含动态加载的数据)
#需求的实现:爬取了一页的数据
import re
import os
url = 'http://duanziwang.com/category/%E6%90%9E%E7%AC%91%E5%9B%BE/'
page_text = requests.get(url,headers=headers).text #页面源码数据
#新建一个文件夹
dirName = 'imgLibs'
if not os.path.exists(dirName):
os.mkdir(dirName)
#数据解析:每一张图片的地址
ex = '<article.*?<img src="(.*?)" alt=.*?</article>'
img_src_list = re.findall(ex,page_text,re.S) #爬虫中使用findall函数必须要使用re.S
for src in img_src_list:
imgName = src.split('/')[-1]
imgPath = dirName+'/'+imgName
urllib.request.urlretrieve(url=src,filename=imgPath)
print(imgName,'下载成功!!!')
3334500855.jpg 下载成功!!!
1865826151.jpg 下载成功!!!
2591221721.jpeg 下载成功!!!
249789596.png 下载成功!!!
392cbdb4e25246a094490178eb7497d5.gif 下载成功!!!
#进行全站数据的爬取:爬取所有页码的图片数据
#需求的实现
#制定一个通用的url模板,不可以被改变
url = 'http://duanziwang.com/category/搞笑图/%d/'
for page in range(1,4):
new_url = format(url%page)
page_text = requests.get(new_url,headers=headers).text #页面源码数据
#新建一个文件夹
dirName = 'imgLibs'
if not os.path.exists(dirName):
os.mkdir(dirName)
#数据解析:每一张图片的地址
ex = '<article.*?<img src="(.*?)" alt=.*?</article>'
img_src_list = re.findall(ex,page_text,re.S) #爬虫中使用findall函数必须要使用re.S
for src in img_src_list:
imgName = src.split('/')[-1]
imgPath = dirName+'/'+imgName
urllib.request.urlretrieve(url=src,filename=imgPath)
print(imgName,'下载成功!!!')
3334500855.jpg 下载成功!!!
1865826151.jpg 下载成功!!!
2591221721.jpeg 下载成功!!!
249789596.png 下载成功!!!
392cbdb4e25246a094490178eb7497d5.gif 下载成功!!!
- pip install bs4
- pip install lxml
- 实例化一个BeautifulSoup的一个对象,把即将被解析的页面源码内容加载到该对象中
- 调用BeautifulSoup对象中相关的方法和属性进行标签定位和本文数据的提取
- BeautifulSoup(fp,'lxml'):将本地的文件内容加载到该对象中进行数据解析
- BeautifulSoup(page_text,'lxml'):将互联网上请求到的数据加载到该对象中进行数据解析
标签定位:
soup.tagName:定位到第一个出现的tagName标签.返回的是单数
属性定位:soup.find('tagName',attrName='value'),返回的是单数
find_all('tagName',attrName='value')返回的是复数(列表)
选择器定位:select('选择器'),返回的也是一个列表
层级选择器:
大于号:表示一个层级
空格:表示多个层级
取文本
string:只可以将标签中直系的文本取出
text:可以将标签中所有的内容取出
取属性
tag['attrName']
#爬取到首页的页面数据
main_url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(main_url,headers=headers).text
fp = open('./sanguo.txt','a',encoding='utf-8')
#解析章节名称+详情页的url
soup = BeautifulSoup(page_text,'lxml')
a_list = soup.select('.book-mulu > ul > li > a')
for a in a_list:
title = a.string#章节标题
detail_url = 'http://www.shicimingju.com'+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,'下载成功!!!')
fp.close()
第一回·宴桃园豪杰三结义 斩黄巾英雄首立功 下载成功!!!
第二回·张翼德怒鞭督邮 何国舅谋诛宦竖 下载成功!!!
第三回·议温明董卓叱丁原 馈金珠李肃说吕布 下载成功!!!
第四回·废汉帝陈留践位 谋董贼孟德献刀 下载成功!!!
第五回·发矫诏诸镇应曹公 破关兵三英战吕布 下载成功!!!
第六回·焚金阙董卓行凶 匿玉玺孙坚背约 下载成功!!!
第七回·袁绍磐河战公孙 孙坚跨江击刘表 下载成功!!!
安装
pip install lxml
解析原理(流程)
实例化一个etree的对象,将解析的数据加载到该对象中
需要调用etree对象中的xpath方法结合着不同的xpath表达式进行标签定位和文本数据的提取
etree对象的实例化
etree.parse('filePath'):将本都数据加载到etree中
etree.HTML(page_text):将互联网上的数据加载到该对象中
html中所有的标签都是遵从了树状的结构,便于我们实现高效的节点的遍历或者查找(定位)
xpath方法的返回值一定是复数(列表)
标签定位
最左侧的/:xpath表达式式一定要从根标签开始进行定位
非最左侧的/:表示一个层级
最左侧的//:从任意位置进行标签定位(常用)
非最左侧//:表示多个层级
//tagName:定位到所有的tagName标签
属性定位://tagName[@attrName="value"]
索引定位://tagName[index],index索引是从1开始
模糊匹配:
//div[contains(@class, "ng")]
//div[starts-with(@class, "ta")]
取文本
/text():取直系的文本内容。列表只有一个元素
//text():所有的文本内容。列表会有多个列表元素
取属性
/@attrName
url = 'https://www.huya.com/g/lol'
page_text = requests.get(url=url,headers=headers).text
#数据解析
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="box-bd"]/ul/li')
for li in li_list:
#实现局部解析:将局部标签下指定的内容进行解析
#局部解析xpath表达式中的最左侧的./表示的就是xpath方法调用者对应的标签
title = li.xpath('./a[2]/text()')[0]
hot = li.xpath('./span/span[2]/i[2]/text()')[0]
detail_url = li.xpath('./a[1]/@href')[0]
print(title,hot,detail_url)
【100%胜率上钻】弹幕随机 611.0万 https://www.huya.com/kaerlol
单双排【连胜上大师】强势AD目前19-0 277.0万 https://www.huya.com/baozha
莎莉:睡了三个小时的战神开干了 219.6万 https://www.huya.com/836458
峡谷上2080分冲第一:新版野区是爷爷! 170.9万 https://www.huya.com/gushouyu
【重播】12月6日8:00 直播2019全明星赛 167.5万 https://www.huya.com/s
早上好 151.9万 https://www.huya.com/951231
#url模板
url = 'http://pic.netbian.com/4kmeinv/index_%d.html'
for page in range(1,11):
new_url = format(url%page) #只可以表示非第一页的页码连接
if page == 1:
new_url = 'http://pic.netbian.com/4kmeinv/'
page_text = requests.get(new_url,headers=headers).text
tree = etree.HTML(page_text)
li_list = tree.xpath('//*[@id="main"]/div[3]/ul/li')
for li in li_list:
img_name = li.xpath('./a/img/@alt')[0]+'.jpg'
img_name = img_name.encode('iso-8859-1').decode('gbk')
img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0]
print(img_name,img_src)
#待补充
#xpath表达式中管道符的应用
#目的:使得xpath表达式具有更强的通用性
url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url,headers=headers).text
tree = etree.HTML(page_text)
# hot_cities = tree.xpath('//div[@class="bottom"]/ul/li/a/text()')
all_cities = tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="bottom"]/ul/li/a/text()')
all_cities
穿白色裙子的美女 看书 4k美女壁纸.jpg http://pic.netbian.com/uploads/allimg/191121/223811-1574347091a133.jpg
居家小清新白色小吊带美女4k壁纸.jpg http://pic.netbian.com/uploads/allimg/190902/152344-1567409024af8c.jpg
白色睡裙美女 侧躺 书 烛光 4k美女壁纸3840x2160.jpg http://pic.netbian.com/uploads/allimg/191129/185356-1575024836972e.jpg
# 目的:使得xpath表达式具有更强的通用性
url = 'https://www.aqistudy.cn/historydata/'
page_text = requests.get(url,headers=headers).text
tree = etree.HTML(page_text)
# hot_cities = tree.xpath('//div[@class="bottom"]/ul/li/a/text()')
all_cities = tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="bottom"]/ul/li/a/text()')
all_cities
# 待补充
原文:https://www.cnblogs.com/zhangdadayou/p/11999870.html