day02
回顾
-
爬虫
-
爬虫的分类:
-
通用
-
聚焦
-
增量式:监测
-
-
反爬机制
-
反反爬策略
-
robots,UA监测:UA伪装
-
http&https概念:服务器和客户端进行数据交互的某种形式
-
常用的头信息:
-
User-Agent:请求载体的身份标识
-
Connection:close
-
content-type
-
-
https的加密方式:证书秘钥加密
-
证书:是被应用在https的加密操作中的.该证书是有证书认证机构颁布的,证书中包含了公钥(加密方式)
-
-
requests:
-
get/post:
-
url
-
data/params:对请求参数的封装
-
headers:UA伪装
-
-
什么是动态加载的数据:由另一个额外的请求请求到的数据
-
ajax
-
js
-
-
如何鉴定页面中是否有动态加载的数据?
-
局部搜索
-
全局搜索
-
-
对一个陌生网站进行爬取前的第一步做什么?
-
确定你要爬取的数据是否为动态加载的!!!
-
-
数据解析
-
解析:根据指定的规则对数据进行提取
-
作用:实现聚焦爬虫
-
聚焦爬虫的编码流程:
-
指定url
-
发起请求
-
获取响应数据
-
数据解析
-
持久化存储
-
-
数据解析的方式:
-
正则
-
bs4
-
xpath
-
pyquery(拓展)
-
-
数据解析的通用原理是什么?
-
数据解析需要作用在页面源码中(一组html标签组成的)
-
html的核心作用是什么?
-
展示数据
-
-
html是如何展示数据的呢?
-
html所要展示的数据一定是被放置在html标签之中,或者是在属性中.
-
-
通用原理:
-
1.标签定位
-
2.取文本or取属性
-
-
正则实现的数据解析
-
需求:爬取糗事百科中糗图数据
-
如何爬取图片数据
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
#方式1:
url = 'https://pic.qiushibaike.com/system/pictures/12217/122176396/medium/OM37E794HBL3OFFF.jpg'
img_data = requests.get(url=url,headers=headers).content #content返回的是byte类型的数据
with open('./123.jpg','wb') as fp:
fp.write(img_data)
#方式2:
from urllib import request
url = 'https://pic.qiushibaike.com/system/pictures/12217/122176396/medium/OM37E794HBL3OFFF.jpg'
request.urlretrieve(url,'./456.jpg')
-
方式1和方式2对于图片数据爬取的操作最大的不同之处是在哪?
-
-
urllib就是一个比较老的网络请求的模块,在requests模块没有出现之前,请求发送的操作使用的都是urllib
#糗事百科 import re import os dir_name = './qiutuLibs' if not os.path.exists(dir_name): os.mkdir(dir_name) url = 'https://www.qiushibaike.com/pic/' page_text = requests.get(url,headers=headers).text #数据解析:图片地址 ex = '<div class="thumb">.*?<img src="(.*?)" alt=.*?</div>' img_src_list = re.findall(ex,page_text,re.S) for src in img_src_list: src = 'https:'+src img_name = src.split('/')[-1] img_path = dir_name+'/'+img_name #对图片地址单独发起请求获取图片数据 request.urlretrieve(src,img_path) print(img_name,'下载成功!!!')
-
爬取多页
-
分析:每一个页码对应的url是有共性:https://www.qiushibaike.com/pic/page/%d/
dir_name = './qiutuLibs' if not os.path.exists(dir_name): os.mkdir(dir_name) #指定一个通用的url模板(不可变) url = 'https://www.qiushibaike.com/pic/page/%d/' for page in range(1,5): print('正在爬取第{}页的图片'.format(page)) #形成一个某页码完整的url new_url = format(url%page) page_text = requests.get(new_url,headers=headers).text #数据解析:图片地址 ex = '<div class="thumb">.*?<img src="(.*?)" alt=.*?</div>' img_src_list = re.findall(ex,page_text,re.S) for src in img_src_list: src = 'https:'+src img_name = src.split('/')[-1] img_path = dir_name+'/'+img_name #对图片地址单独发起请求获取图片数据 request.urlretrieve(src,img_path) # print(img_name,'下载成功!!!')
bs4解析
-
环境的安装:
-
-
pip install lxml
-
-
bs4的解析原理
-
实例化一个BeautifulSoup的对象,并且将即将被解析的页面源码数据加载到该对象中
-
调用BeautifulSoup对象中的相关属性和方法进行标签定位和数据提取
-
-
如何实例化BeautifulSoup对象呢?
-
BeautifulSoup(fp,'lxml'):专门用作于解析本地存储的html文档中的数据
-
BeautifulSoup(page_text,'lxml'):专门用作于将互联网上请求到的页面源码数据进行解析
-
标签定位
-
soup.tagName:定位到第一个TagName标签,返回的是单数
-
属性定位:soup.find('tagName',attrName='value'),返回也是单数
-
find_all:和find用法一致,但是返回值是列表
-
-
选择器定位:select('选择器'),返回值为列表
-
标签,类,id,层级(>:一个层级,空格:多个层级)
-
提取数据
-
取文本:
-
tag.string:标签中直系的文本内容
-
tag.text:标签中所有的文本内容
-
-
取属性:
-
tag['attrName']
-
from bs4 import BeautifulSoup fp = open('./test.html','r',encoding='utf-8') soup = BeautifulSoup(fp,'lxml') #将即将被解析的页面源码加载到该对象中 soup.p soup.find('div',class_='song') soup.find_all('div',class_='song') soup.select('.tang') soup.select('#feng') soup.select('.tang > ul > li') soup.select('.tang li') li_6 = soup.select('.tang > ul > li')[6] i_tag = li_6.i i_tag.string soup.find('div',class_='tang').text soup.find('a',id="feng")['href'] 'http://www.haha.com'
-
爬取三国演义整篇小说内容
http://www.shicimingju.com/book/sanguoyanyi.html
-
章节名称
-
章节内容
-
#在首页中解析章节名称&每一个章节详情页的url url = 'http://www.shicimingju.com/book/sanguoyanyi.html' page_text = requests.get(url,headers=headers).text soup = BeautifulSoup(page_text,'lxml') a_list = soup.select('.book-mulu > ul > li > a') fp = open('sanguo.txt','w',encoding='utf-8') for a in a_list: detail_url = 'http://www.shicimingju.com'+a['href'] chap_title = a.string #对章节详情页的url发起请求,解析详情页中的章节内容 detail_page_text = requests.get(detail_url,headers=headers).text soup = BeautifulSoup(detail_page_text,'lxml') chap_content = soup.find('div',class_="chapter_content").text fp.write(chap_title+':'+chap_content+'\n') print(chap_title,'爬取成功!') fp.close()
xpath解析
-
环境的安装:pip install lxml
-
xpath的解析原理
-
实例化一个etree类型的对象,且将页面源码数据加载到该对象中
-
需要调用该对象的xpath方法结合着不同形式的xpath表达式进行标签定位和数据提取
-
-
etree对象的实例化
-
etree.parse(fileNane)
-
etree.HTML(page_text)
-
-
xpath方法返回的永远是一个列表
标签定位
-
在xpath表达式中最最侧的/表示的含义是说,当前定位的标签必须从根节点开始进行定位
-
xpath表达式中最左侧的//表示可以从任意位置进行标签定位
-
xpath表达式中非最左侧的//表示的是多个层级的意思
-
xpath表达式中非最左侧的/表示的是一个层级的意思
-
属性定位://tagName[@arrtName='value']
-
索引定位://tagName/li[3]
提取数据
-
取文本:
-
/text():取直系的文本内容
-
//text():取所有的文本内容
-
-
取属性:
-
tag/@attrName
-
from lxml import etree tree = etree.parse('./test.html') tree.xpath('/html/head/meta')[0] #绝对路径 tree.xpath('//meta')[0] #相对路径,将整个页面源码中所有的meta进行定位 tree.xpath('/html//meta')[0] #属性定位 tree.xpath('//div[@class="song"]') #索引定位 tree.xpath('//div[@class="tang"]/ul/li[3]') #该索引是从1开始 tree.xpath('//div[@class="tang"]//li[3]') #该索引是从1开始 #取文本 tree.xpath('//p[1]/text()') tree.xpath('//div[@class="song"]//text()') #取属性 tree.xpath('//a[@id="feng"]/@href') ['http://www.haha.com']
-
需求:爬取boss的招聘信息
-
岗位名称
-
公司名称
-
薪资
-
岗位描述
-
headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36', 'cookie':"" } url = 'https://www.zhipin.com/job_detail/?query=python%E7%88%AC%E8%99%AB&city=101010100&industry=&position=' page_text = requests.get(url,headers=headers).text #数据解析 tree = etree.HTML(page_text) li_list = tree.xpath('//div[@class="job-list"]/ul/li') for li in li_list: # 需要将li表示的局部页面源码数据中的相关数据进行提取 # 如果xpath表达式被作用在了循环中,表达式要以./或者.//开头 detail_url = 'https://www.zhipin.com'+li.xpath('.//div[@class="info-primary"]/h3/a/@href')[0] job_title = li.xpath('.//div[@class="info-primary"]/h3/a/div/text()')[0] salary = li.xpath('.//div[@class="info-primary"]/h3/a/span/text()')[0] company = li.xpath('.//div[@class="info-company"]/div/h3/a/text()')[0] #对详情页的url发请求解析出岗位职责 detail_page_text = requests.get(detail_url,headers=headers).text tree = etree.HTML(detail_page_text) job_desc = tree.xpath('//div[@class="text"]//text()') job_desc = ''.join(job_desc) print(job_title,salary,company,job_desc)
-
另一种较为通用的xpath表达式的使用形式:管道符在xpath表达式中的应用,用于解析不规则布局的页面数据
-
爬取糗事百科的段子内容和作者名称
headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36', } url = 'https://www.qiushibaike.com/text/page/4/' page_text = requests.get(url,headers=headers).text tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="content-left"]/div') for div in div_list: author = div.xpath('./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()')[0] content = div.xpath('.//div[@class="content"]/span//text()') content = ''.join(content) print(author,content)
中文乱码处理的问题
-
爬取http://pic.netbian.com/4kmeishi/的图片和图片名称
#指定一个通用的url模板 url = 'http://pic.netbian.com/4kmeishi/index_%d.html' for page in range(1,3): if page == 1: new_url = 'http://pic.netbian.com/4kmeishi/' else: new_url = format(url%page) response = requests.get(new_url,headers=headers) #response.encoding = 'utf-8' page_text = response.text tree = etree.HTML(page_text) li_list = tree.xpath('//*[@id="main"]/div[3]/ul/li') for li in li_list: img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0] img_name = li.xpath('./a/b/text()')[0] img_name = img_name.encode('iso-8859-1').decode('gbk')

浙公网安备 33010602011771号