爬虫之数据解析
数据解析可以为我们实现聚焦爬虫
- 正则
- bs4
- xpath
- pyquery
聚焦爬虫要获取的数据都被存储在了相关标签的属性中
- 定位标签
- 获取文本或者属性
爬取一张图片
import requests headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } url = 'https://c-ssl.duitang.com/uploads/item/201502/22/20150222193803_yhrNV.jpeg' img_data = requests.get(url,headers=headers).content # bytes类型数据 with open('./img.jpg','wb') as fp: fp.write(img_data)
一个自带写入文件功能的模块
# 不能使用ua认证 # Python内置的一个基于请求响应的功能 from urllib import request url = 'https://c-ssl.duitang.com/uploads/item/201502/22/20150222193803_yhrNV.jpeg' request.urlretrieve(url,filename='./a.jpg') # 自带写入文件的功能
正则
#糗图爬取1-3页所有的图片
#1.使用通用爬虫将前3页对应的页面源码数据进行爬取
#通用的url模板(不可变)
import os import sys import re import requests from urllib import request page_count = input('爬取页数: ') DirName = './ImgFile' if not os.path.exists(DirName): os.mkdir(DirName) headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36' } for page in range(1, int(page_count)+1): url = f'https://www.qiushibaike.com/imgrank/page/{page}/' 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) count = 0 for src in img_src_list: img_url = 'https:' + src # 图片完整网址 img_name = os.path.basename(img_url) # 获取图片名 img_path = os.path.join(DirName,img_name) # 拼接图片保存路径 request.urlretrieve(img_url, img_path) # 一步到位保存文件 count += 1 print_str = f"正在抓取第{page}页第{count}条数据" print(print_str) print('数据抓取完毕')
bs4解析
- 实例化一个BeautifulSoup对象,需要将即将被解析的页面源码数据加载到该对象中
- 调用BeautifulSoup对象中的相关方法和属性进行标签定位和数据提取
# bs4的安装
pip install bs4
pip install lxml
BeautifulSoup的实例化
- BeautifulSoup(fp,'lxml'):将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中
- BeautifulSoup(page_text,'lxml'):将从互联网上获取的页面源码数据加载到实例化好的BeautifulSoup对象中
定位标签的操作
- soup.tagName: 定位到第一个出现的tagName标签
- 属性定位: soup.find('tagName',attrName='value')
- 属性定位: soup.find_all('tagName',attrName='value'),返回值为列表
- 选择器定位: soup.select('选择器')
- 层级选择器: >表示一个层级 空格表示多个层级
获取文本
- .string:获取直系的文本内容
- .text:获取所有的文本内容
获取属性
- tagName'attrName'
from bs4 import BeautifulSoup fp = open('./test.html','r',encoding='utf-8') # 将本地存储的一个html文档中的数据加载到实例化好的BeautifulSoup对象中 soup = BeautifulSoup(fp, 'lxml') # html源码 # 获取第一个出现的div标签 a = soup.div a = soup.find('div') # 属性定位 a = soup.find('div', class_='song') a = soup.find('a', id='feng') # 匹配所有符合要求的 a = soup.find_all('div') a = soup.find_all('div', class_='song') a = soup.find_all('a', class_='du') # 选择器定位 获取到的是一个list列表 a = soup.select('#feng')[0] # 层级选择器 a = soup.select('.tang > ul > li') # > 号表示一个层级 a = soup.select('.tang li') # 空格表示多个层级 # 获取当前层级中所有的文本 a_tag = soup.select('#feng')[0] a = a_tag.text # 获取当前层级中直系的文本 a_tag = soup.find('div',class_='tang') a = a_tag.string # None # 获取标签属性 a_tag = soup.select('#feng')[0] a = a_tag['href'] print(a)
bs4示例爬虫
# http://www.shicimingju.com/book/ # 爬取古籍 # 例: 三国志 import requests from bs4 import BeautifulSoup url = 'http://www.shicimingju.com' poetry_url = 'http://www.shicimingju.com/book/sanguozhi.html' file = open('三国志.txt','a',encoding='utf-8') headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } page_text = requests.get(url=poetry_url,headers=headers).text soup = BeautifulSoup(page_text,'lxml') page_list = soup.select('.book-mulu > ul > li > a') for page in page_list: page_name = page.string page_url = url + page['href'] book_text = requests.get(url=page_url, headers=headers).text book_soup = BeautifulSoup(book_text, 'lxml') book_txt = book_soup.find('div', class_='chapter_content').text txt = page_name + '\n' + book_txt + '\n' file.write(txt) print(f'章节{page_name}下载完毕') file.close()
xpath解析
- 实例化一个etree的对象,然后将即将被解析的页面源码加载到改对象中
- 使用etree对象中的xpath方法结合着不同形式的xpath表达式实现标签定位和数据提取
安装: pip install lxml
etree对象的实例化
etree.parse('test.html') 加载本地的html
etree.HTML(page_text)
xpath表达式:xpath方法的返回值一定是一个列表
- 最左侧的/表示:xpath表达式一定要从根标签逐层进行标签查找和定位
- 最左侧的//表示:xpath表达式可以从任意位置定位标签
- 非最左侧的/:表示一个层级
- 非最左侧的//:表示夸多个层级
- 属性定位://tagName@attrName="value"
- 索引定位://tagNameindex 索引是从1开始
取文本:
- /text():直系文本内容
- //text():所有的文本内
取属性:
- /@attrName
from lxml import etree # 加载本地html tree = etree.parse('./test.html') # xpath返回的是一个列表 # 绝对路径匹配 逐层标签查找 a = tree.xpath('/html/head/title') a = tree.xpath('/html/body/div/p') # 相对路径 从任意位置定位标签 a = tree.xpath('//p') # //表示多个层级 a = tree.xpath('//div//li') # 属性查找 a = tree.xpath("//div[@class='song']") # 索引定位,定位第七个li标签,索引从1开始计数 a = tree.xpath('//li[7]') # 获取文本 # 获取直系文本 a = tree.xpath("//a[@class='du']/text()")[0] # 获取所有文本 a = tree.xpath("//div[@class='song']//text()") # 获取属性 a = tree.xpath("//a[@id='feng']/@href") print(a)
xpath示例代码
from lxml import etree import requests init_url = 'https://www.qiushibaike.com' url = 'https://www.qiushibaike.com/text/' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } html_text = requests.get(url=url, headers=headers).text tree = etree.HTML(html_text) html_list = tree.xpath("//a[@class='contentHerf']/@href") for html in html_list: new_url = init_url + html # 实现局部解析 new_text = requests.get(url=new_url, headers=headers).text txt_tree = etree.HTML(new_text) content = txt_tree.xpath("//div/div[@class='content']//text()") content = ''.join(content) print(content)
# http://pic.netbian.com/4kdongman/index.html import os import sys import requests from urllib import request from lxml import etree ImgFile = '4K动漫壁纸' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } url = f'http://pic.netbian.com/4kdongman/index_%d.html' img_in_url = 'http://pic.netbian.com' if not os.path.exists(ImgFile): os.mkdir(ImgFile) for page in range(1,11): if page == 1: new_url = 'http://pic.netbian.com/4kdongman/index.html' else: new_url = url%page int_htm = requests.get(url=new_url,headers=headers).text ini_obj = etree.HTML(int_htm) img_hm_lis = ini_obj.xpath("//div[@class='slist']//li/a/@href") for hml in img_hm_lis: img_src = img_in_url + hml img_url = requests.get(url=img_src,headers=headers).text img = etree.HTML(img_url) img = img.xpath("//a[@id='img']/img/@src")[0] ImgName = os.path.basename(img) ImgPath = os.path.join(ImgFile, ImgName) ImgUrl = img_in_url+img request.urlretrieve(ImgUrl, filename=ImgPath) print(ImgName,'下载完成')
# 获取所有城市名 https://www.aqistudy.cn/historydata/

浙公网安备 33010602011771号