当前位置 : 主页 > 编程语言 > python >

Python--爬虫数据解析

来源:互联网 收集:自由互联 发布时间:2022-06-15
页面解析和数据提取 一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为两部分,非结构化的数据 和 结构化的数据。 非结构化数据:先

页面解析和数据提取

一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为两部分,非结构化的数据 和 结构化的数据。

  • 非结构化数据:先有数据,再有结构,(​​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内容

<html><body>
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
</body></html>

1.获取所有的

  • 标签
from lxml import etree
html = etree.parse('hello.html')

result = html.xpath('//li')

print(result) # 打印<li>标签的元素集合

result_text = html.xpath('//li/text()')

2.获取

  • 标签的所有class属性
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.继续获取​​<li>​​​标签下​​href​​​为 ​​link1.html​​​ 的 ​​<a>​​ 标签

from lxml import etree

html = etree.parse('hello.html')
result = html.xpath('//li/a[@href="link1.html"]')

print result

运行结果

[<Element a at 0x10ffaae18>]

4.获取最后一个 ​​<li>​​​ 的 ​​<a>​​ 的 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--Selenium库使用
下一篇:没有了
网友评论