Python--爬虫数据解析
2021-04-12 15:28
标签:value 作者 agent att 源码 乱码 属性 sele rap
页面解析和数据提取
一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为两部分,非结构化的数据 和 结构化的数据。
-
非结构化数据:先有数据,再有结构,(http://www.baidu.com)
-
结构化数据:先有结构、再有数据(https://www.qiushibaike.com/imgrank/page/3/)
-
不同类型的数据,我们需要采用不同的方式来处理。
常用的数据解析有正则(re)、bs4、xpath等。
正则使用参考
?
bs4
bs4解析原理
- 实例化一个BeautifulSoup的对象,需要将即将被解析的页面源码数据加载到对象中
- 调用BeautifulSoup对象中的相关方法和属性进行标签定位和数据提取
?
bs4解析流程
?? 环境安装
pip install bs4
?? 导入模块
from bs4 import BeautifulSoup
?? 实例化一个BeautifulSoup对象
# 转化本地文件(将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中)
soup = BeautifulSoup(open(‘本地文件‘), ‘lxml‘)
# 转化网络文件(将从互联网上获取的页面源码数据加载到实例化好的BeautifulSoup对象中)
soup = BeautifulSoup(‘字符串类型或者字节类型‘, ‘lxml‘)
?? 调用BeautifulSoup对象中的相关属性和方法进行标签的定位
?
bs4基本语法
1.根据标签名查找
soup.tagName
- soup.a 只能找到第一个符合要求的标签
2.获取属性
soup.tagName[‘attrName‘]
- soup.a.attrs 获取a所有的属性和属性值,返回一个字典
- soup.a.attrs[‘href‘] 获取href属性
- soup.a[‘href‘] 也可简写为这种形式
3.获取内容
.string:获取直系的文本内容
.text:获取所有的文本内容
- soup.a.string 获取a标签的直系文本
- soup.a.text 这是属性,获取a子类的所有文本
- soup.a.get_text() 这是方法,获取a标签子类的所有文本
【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
4.属性定位find方法
soup.find(‘tagName‘, attrName=‘value‘)
- soup.find(‘a‘) 找到第一个符合要求的a标签
- soup.find(‘a‘, title="xxx") 找具有title=xxx属性的第一个a标签
- soup.find(‘li‘, alt="xxx") 找到具有alt=xxx属性的第一个li标签
- soup.find(‘ul‘, class_="xxx") 找到具有class=xxx属性的第一个ui标签
- soup.find(‘div‘, id="xxx") 找到具有id=xxx属性的第一个div标签
5.属性定位find_all方法
soup.find_all(‘tagName‘, attrName=‘value‘),返回值为列表
- soup.find_all(‘a‘) #找到所有a标签
- soup.find_all(‘a‘, title=‘xxx‘) 找到具有title=xxx属性的所有a标签
- soup.find_all(‘div‘, class_=‘xxx‘, limit=3) 找到具有class=xxx属性的前三个标签
6.选择器定位select方法
soup.select(‘选择器‘)
- soup.select(‘.song‘) 找到类属性为song的标签
- soup.select(‘#song‘) 找到id属性为song的标签
- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
- 层级选择器:
div .haha #wan 空格表示多个层级
div > p > a > img >表示一个层级
?
bs4爬虫示例
?? 爬取三国整篇内容
#爬取三国整篇内容(章节名称和章节内容) http://www.shicimingju.com/book/sanguoyanyi.html
import requests
from bs4 import BeautifulSoup
fp = open(‘sanguo.txt‘,‘w‘,encoding=‘utf-8‘)
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
}
main_url = ‘http://www.shicimingju.com/book/sanguoyanyi.html‘
page_text = requests.get(url=main_url, headers=headers).text
#解析出章节名称和章节详情的url
soup = BeautifulSoup(page_text, ‘lxml‘)
a_list = soup.select(‘.book-mulu > ul >li > a‘) #返回的列表中存储的是一个个a标签
for a in a_list:
title = a.string
detail_url = ‘http://www.shicimingju.com‘+a[‘href‘]
detail_page_text = requests.get(detail_url, headers=headers).text
#解析详情页中的章节内容
soup = BeautifulSoup(detail_page_text, ‘lxml‘)
content = soup.find(‘div‘, class_=‘chapter_content‘).text
fp.write(title+‘:‘+content+‘\n‘)
print(title,‘下载成功!‘)
fp.close
?
xpath
xpath解析原理
- 实例化一个etree的对象,然后将即将被解析的页面源码加载到该对象中
- 使用etree对象中xpath方法结合着不同形式的xpath表达式实现标签定位和数据提取
?
xpath解析流程
?? 环境安装
pip install lxml
?? 导入模块
from lxml import etree
?? 实例化一个etree对象
# 转化本地文件(将本地存储的一个html文档中的数据加载到实例化好的tree对象中)
tree = etree.parse(‘test.html‘)
# 转化网络文件(将从互联网上获取的页面源码数据加载到实例化好的tree对象中)
tree = etree.HTML(page_text)
?
xpath基本语法
xpath表达式:xpath方法的返回值一定是一个列表
最左侧的/表示:xpath表达式一定要从根标签逐层进行标签查询和定位
最左侧的//表示:xpath表达式可以从任意位置定位标签
非最左侧的/:表示一个层级
非最左侧的//:表示夸多个层级
属性定位://tagName[@attrName=‘value‘]
索引定位://tagName[index] 索引从1开始
1.取文本:
- /text():直系文本内容
- //text():所有文本内容
2.取属性:
/@attrName
示例
准备html内容
- first item
- second item
- third item
- fourth item
- fifth item
1.获取所有的
from lxml import etree
html = etree.parse(‘hello.html‘)
result = html.xpath(‘//li‘)
print(result) # 打印标签的元素集合
result_text = html.xpath(‘//li/text()‘)
2.获取
from lxml import etree
html = etree.parse(‘hello.html‘)
result = html.xpath(‘//li/@class‘)
print result
结果是
[‘item-0‘, ‘item-1‘, ‘item-inactive‘, ‘item-1‘, ‘item-0‘]
3.继续获取标签下
href
为 link1.html
的 标签
from lxml import etree
html = etree.parse(‘hello.html‘)
result = html.xpath(‘//li/a[@href="http://www.mamicode.com/link1.html"]‘)
print result
运行结果
[]
4.获取最后一个 的
的 href
from lxml import etree
html = etree.parse(‘hello.html‘)
result = html.xpath(‘//li[last()]/a/@href‘)
# 谓语 [last()] 可以找到最后一个元素
print result
运行结果
[‘link5.html‘]
?
xpath 爬虫示例
?? 示例1
#爬取糗事百科中段子内容和作者名称
import requests
from lxml import etree
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
}
url = ‘https://www.qiushibaike.com/text/‘
page_text = requests.get(url=url, headers=headers).text
#解析内容
tree = etree.HTML(page_text)
div_list = tree.xpath(‘//div[@class="col1 old-style-col1"]/div‘)
for div in div_list:
author = div.xpath(‘./div[1]/a[2]/h2/text()‘)[0] #实现局部解析
content = div.xpath(‘./a[1]/div/span//text()‘)
content = ‘‘.join(content)
print(author, content)
?? 示例2
# http://pic.netbian.com/4kmeinv/ 联系xpath和解决中文乱码问题
dirName = ‘./meinvLibs‘
if not os.path.exists(dirName):
os.mkdir(dirName)
url = ‘http://pic.netbian.com/4kmeinv/index_%d.html‘
for page in range(1,11):
if page == 1:
new_url = ‘http://pic.netbian.com/4kmeinv/‘
else:
new_url = format(url%page)
page_text = requests.get(url=new_url, headers=headers).text
tree = etree.HTML(page_text)
a_list = tree.xpath(‘//div[@class="slist"]/ul/li/a‘)
for a in a_list:
img_src = ‘http://pic.netbian.com‘ + a.xpath(‘./img/@src‘)[0]
img_name = a.xpath(‘./b/text()‘)[0]
img_name = img_name.encode(‘iso-8859-1‘).decode(‘gbk‘)
img_data = requests.get(url=img_src, headers=headers).content
imgPath = dirName+‘/‘+img_name+‘.jpg‘
with open(imgPath, ‘wb‘) as fp:
fp.write(img_data)
print(img_name, "下载成功!!!")
?? 示例3
# http://sc.chinaz.com/jianli/free.html 爬取简历模板前五页 通过xpath解析
import requests, os
from lxml import etree
save_resume_dir = ‘./jianli‘
if not os.path.exists(save_resume_dir):
os.mkdir(save_resume_dir)
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
}
url = ‘http://sc.chinaz.com/jianli/free_%d.html‘
for page in range(1,6):
if page == 1:
new_url = ‘http://sc.chinaz.com/jianli/free.html‘
else:
new_url = format(url%page)
page_text = requests.get(url=new_url, headers=headers).text #向每一页发起请求
tree = etree.HTML(page_text)
a_list = tree.xpath(‘//div[@id="container"]/div/a‘) #获取每一页中所有的简历
for a in a_list:
resume_url = a.xpath(‘./@href‘)[0] #得到每一份简历的url地址
resume_anme = a.xpath(‘./img/@alt‘)[0] #得到每一份简历的名字
resume_anme = resume_anme.encode(‘iso-8859-1‘).decode(‘utf-8‘) #解决简历名字乱码
resume_text = requests.get(url=resume_url, headers=headers).text #向每一份简历的页面发起请求
tree = etree.HTML(resume_text)
resume_down_url = tree.xpath(‘//div[@class="down_wrap"]/div[2]/ul/li[1]/a/@href‘)[0] #对每一份简历页面请求数据进行解析,得到下载的url
resume_down_text = requests.get(url=resume_down_url, headers=headers).content #下载每一份简历
resume_path = save_resume_dir + ‘/‘ + resume_anme + ‘.rar‘
with open(resume_path, ‘wb‘) as fp:
fp.write(resume_down_text)
print(resume_anme+‘简历模板下载成功!!!‘)
?? 示例4
# 爬取梨视频任意板块最热视频 https://www.pearvideo.com/category_8
import requests
from lxml import etree
import re
headers = {
‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36‘
}
main_url = ‘https://www.pearvideo.com/category_8‘
main_text = requests.get(url=main_url, headers=headers).text
tree = etree.HTML(main_text)
div_list = tree.xpath(‘//*[@id="listvideoListUl"]/li‘)
for li in div_list:
detile_url = ‘https://www.pearvideo.com/‘ + li.xpath(‘./div/a/@href‘)[0] #获取视频详情页
title = li.xpath(‘./div/a/div[2]/text()‘)[0] + ‘.mp4‘ #获取视频名字
detile_page_text = requests.get(url=detile_url, headers=headers).text #向视频详情页发起请求
ex = ‘srcUrl="(.*?)",vdoUrl‘ #通过正则获取js动态加载的数据
video_url = re.findall(ex, detile_page_text, re.S)[0] #解析出视频url的地址
video_data = requests.get(video_url, headers=headers).content #对视频url发起请求进行下载
with open(f‘./video/{title}‘, ‘wb‘) as fp:
fp.write(video_data)
Python--爬虫数据解析
标签:value 作者 agent att 源码 乱码 属性 sele rap
原文地址:https://www.cnblogs.com/yanjieli/p/13353926.html
上一篇:Python之__slots__
下一篇:JavaScript预览图片