爬虫的数据解析, 正则 ,bs ,xpath
爬虫的数据解析
两种爬取图片的方法
- 第一种: 使用with open 保存为文件
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
img_url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559019106959&di=3aa954df95d2e55083d85de8391118c5&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201601%2F28%2F20160128195606_xvawC.jpeg'
img_data = requests.get(url=img_url,headers=headers).content
with open('./meinv.jpg','wb') as fp:
fp.write(img_data)
- 第二种: 使用urllib模块
from urllib import request
img_url = 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559019106959&di=3aa954df95d2e55083d85de8391118c5&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201601%2F28%2F20160128195606_xvawC.jpeg'
request.urlretrieve(img_url,'./meishaonv.jpg')
数据解析
常用的python数据解析有四种方式:
- 正则
- xpath
- bs4
- pyquery
数据解析的原理:
- 标签的定位
- 提取标签中存储的文本数据或者标签属性中存储的数据
1.正则解析:
- 示例
- 需求:爬取糗事百科中所有的糗图图片数据
- 实现:
- 检查页面中的图片数据是否为动态加载的
- 将当前页面的源码数据请求到
- 使用正则表达式定位相关的img标签,然后获取img的src属性值
- 对src的属性值发起请求获取图片数据
- 持久化存储图片数据
对页面的分析:
可以看到要提取img标签中的src属性
<div class="thumb">
<a href="/article/121858876" target="_blank">
<img src="//pic.qiushibaike.com/system/pictures/12185/121858876/medium/VFMNF2Z1GNEYXR3A.jpg" alt="求大神制作">
</a>
</div>
实现:
import os
import requests
import re
from urllib import request
if not os.path.exists('./qiutu'):
os.mkdir('./qiutu')
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
url = 'https://www.qiushibaike.com/pic/'
page_text = requests.get(url=url,headers=headers).text
ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
img_url = re.findall(ex,page_text,re.S)
for url in img_url:
url = 'https:'+url
img_name = url.split('/')[-1]
img_path = './qiutu/'+img_name
request.urlretrieve(url,img_path)
print(img_name,'下载成功!!!')
2.bs4解析(beautifulsoup4)
- 解析原理:
- 实例化一个Beautifulsoup的对象,且将页面源码数据加载到该对象中
- 使用该对象的相关属性和方法实现标签定位和数据提取
- 环境的安装:
- pip install bs4
- pip install lxml
- 实例化Beautifulsoup对象
- BeautifulSoup(page_text,'lxml'):将从互联网上请求到的页面源码数据加载到该对象中
- BeautifulSoup(fp,'lxml'):将本地存储的一样页面源码数据加载到该对象中
bs4模块的基本使用
示例的文件为当前准备的test.html文件
from bs4 import BeautifulSoup
fp = open('./test.html','r',encoding='utf-8')
soup = BeautifulSoup(fp,'lxml')
1.soup.tagName:只可以定位到第一次出现的tagName标签
soup.title
soup.div
2.soup.find(‘tagName’)
#soup.find(‘tagName’)
soup.find('a') # soup.a
#属性定位
soup.find('div',class_='song')
结果如下
<div class="song">
<p>李清照</p>
<p>王安石</p>
<p>苏轼</p>
<p>柳宗元</p>
<a href="http://www.song.com/" target="_self" title="赵匡胤">
<span>this is span</span>
宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
<a class="du" href="">总为浮云能蔽日,长安不见使人愁</a>
<img alt="" src="http://www.baidu.com/meinv.jpg"/>
</div>
3.find_all
soup.find_all(‘div’)[2] # 找到所有的div标签中的第3个,
4.select(‘选择器’)
soup.select('.song') # 找到类为.song的标签
soup.select('div')
soup.select('.tang > ul > li > a')
soup.select('.tang a')
示例:爬取古诗文网的三国演义小说
- 页面数据是否为动态加载
- 在首页中解析章节标题和标题对应的详情页的url
- 对详情页url发起请求获取详情页的源码数据
- 检查详情页是否存在动态加载的数据
- 解析详情页中的章节内容
- 持久化存储
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(url=url,headers=headers).text
#数据解析:标题和url
soup = BeautifulSoup(page_text,'lxml')
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']
# print(title,detail_url)
#单独对详情页发起请求获取源码数据
detail_page_text = requests.get(url=detail_url,headers=headers).text
soup = BeautifulSoup(detail_page_text,'lxml')
content = soup.find('div',class_="chapter_content").text
fp.write(title+'\n'+content+'\n')
print(title,':下载成功!')
fp.close()
3.xpath解析
- 解析效率比较高
- 通用性最强的
- 环境安装:pip install lxml
- 解析原理:
- 实例化一个etree对象且将即将被解析的页面源码数据加载到该对象中
- 使用etree对象中的xpath方法结合着xpath表达式进行标签定位和数据提取
- 实例化etree对象
- etree.parse('本地文件路径')
- etree.HTML(page_text)
from lxml import etree
tree = etree.parse('./test.html')
定位title标签
tree.xpath('/html/head/title')
tree.xpath('/html//title')
tree.xpath('//title')
定位class=song的div
tree.xpath('//div[@class="song"]')
tree.xpath('//div[2]') #xpath表达式中的索引是从1开始
取文本
#取文本(获取李清照) /text() //text()
tree.xpath('//div[@class="song"]/p[1]/text()')[0]
tree.xpath('//div[@class="song"]/text()')
爬取boss直聘的python爬虫岗位信息
解决报错信息: HTTPConnectionPool(host:XX)Max retries exceeded with url
- 及时断开连接:headers =
- 更换请求对应的ip
#boss直聘
url = 'https://www.zhipin.com/job_detail/?query=python%E7%88%AC%E8%99%AB&city=101010100&industry=&position='
page_text = requests.get(url=url,headers=headers).text
#数据解析(jobTitle,salary,company)
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="job-list"]/ul/li')
for li in li_list:
title = li.xpath('.//div[@class="job-title"]/text()')[0]
salary = li.xpath('.//span[@class="red"]/text()')[0]
company = li.xpath('.//div[@class="company-text"]/h3/a/text()')[0]
print(title,salary,company)