一.两种爬取图片的方法
①requests方法
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)
②request方法
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') #图片,压缩包,视频等一定要加好后缀
二.数据解析
1.正则
单字符: . : 除换行以外所有字符 [] :[aoe] [a-w] 匹配集合中任意一个字符 d :数字 [0-9] D : 非数字 w :数字、字母、下划线、中文 W : 非w s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ f v]。 S : 非空白 数量修饰: * : 任意多次 >=0 + : 至少1次 >=1 ? : 可有可无 0次或者1次 {m} :固定m次 hello{3,} {m,} :至少m次 {m,n} :m-n次 边界: $ : 以某某结尾 ^ : 以某某开头 分组: (ab) 贪婪模式: .* 非贪婪(惰性)模式: .*? re.I : 忽略大小写 re.M :多行匹配 re.S :单行匹配 re.sub(正则表达式, 替换内容, 字符串)
正则解析
需求:爬取糗事百科中所有的糗图图片数据
实现:
检查页面中的图片数据是否为动态加载的
将当前页面的源码数据请求到
使用正则表达式定位相关的img标签,然后获取img的src属性值
对src的属性值发起请求获取图片数据
持久化存储图片数据
import requests import re
import os 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解析
①环境安装
输入
pip3 install bs4
pip3 install lxml
②原理
解析原理:
实例化一个Beautifulsoup的对象,且将页面源码数据加载到该对象中
使用该对象的相关属性和方法实现标签定位和数据提取
实例化Beautifulsoup对象 BeautifulSoup(page_text,'lxml'):将从互联网上请求到的页面源码数据加载到该对象中 BeautifulSoup(fp,'lxml'):将本地存储的一样页面源码数据加载到该对象中
soup = BeautifulSoup(fp,'lxml') #示例化
③定位
#①soup.tagName:只可以定位到第一次出现的tagName标签
soup.title
soup.div
#soup.find(‘tagName’) soup.find('a') # soup.a #②属性定位 soup.find('div',class_='song')
#③find_all soup.find_all('div')[2]
#④select('选择器') soup.select('.song')
‘>’:表示一个层级
soup.select('.tang > ul > li > a')
空格:表示多个层级
soup.select('.tang a')
④取值
#取文本:string取的是直系的文本数据,text获取的是全部的数据 soup.p.string
#取后代中的所有文本数据
soup.find('div',class_='tang').get_text()
soup.find('div',class_='tang').text
#取属性 soup.a['href']
⑤示例
爬取古诗文网的三国演义小说(过程):
页面数据是否为动态加载
在首页中解析章节标题和标题对应的详情页的url
对详情页url发起请求获取详情页的源码数据
检查详情页是否存在动态加载的数据
解析详情页中的章节内容
持久化存储
import requests
from bs4 import BeautifulSoup
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+' '+content+' ') 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开始
tree.xpath('//div[@class="tang"]/ul/li[4]/a')
tree.xpath('//div[@class="tang"]//li[4]/a')
④取值
#取文本(获取李清照) /text() //text() tree.xpath('//div[@class="song"]/p[1]/text()')[0] tree.xpath('//div[@class="song"]/text()')
#取属性 tree.xpath('//a/@title')
⑤示例1
#爬取boss直聘爬虫岗位的信息
from lxml import etree
import requests
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)
⑥示例2(管道符的使用)
#爬取全国城市名称 import requests from lxml import etree url = 'https://www.aqistudy.cn/historydata/' page_text = requests.get(url=url,headers=headers).text tree = etree.HTML(page_text) # hot_city = tree.xpath('//div[@class="bottom"]/ul/li/a/text()') # all_city = tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text()') # all_city tree.xpath('//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="bottom"]/ul/li/a/text()')
⑦示例3(解决中文乱码问题)
#爬取4k图片带标题
import requests from lxml import etree start_page = int(input('start page num:')) end_page = int(input('end page num:')) if not os.path.exists('./meinvs'): os.mkdir('./meinvs') #通用的url模板(不能修改) url = 'http://pic.netbian.com/4kmeinv/index_%d.html' for page in range(start_page,end_page+1): if page == 1: new_url = 'http://pic.netbian.com/4kmeinv/' else: #除第一页外,其他url一致 new_url = format(url%page) response = requests.get(url=new_url,headers=headers) # response.encoding = 'utf-8' #第一种 page_text = response.text #解析名称和图片的src属性值 tree = etree.HTML(page_text) li_list = tree.xpath('//div[@class="slist"]/ul/li') for li in li_list: img_name = li.xpath('./a/img/@alt')[0] img_name = img_name.encode('iso-8859-1').decode('gbk')+'.jpg' #第二种 img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0] img_path = './meinvs/'+img_name request.urlretrieve(img_src,img_path) print(img_name,'下载成功!!!')