2 爬虫 数据解析(bs4,XPath) robots协议 cookie反爬 代理反爬
爬虫
1 数据解析
1.1 介绍
1.1.1 概念即作用
数据解析就是将一组数据中的局部数据进行提取,用于实现聚焦爬虫。
聚焦爬虫是建立在通用爬虫的基础上,从通用爬虫获取的整个源码数据中提取出指定的数据。
1.1.2 聚焦爬虫的流程
- 指定url
- 发起请求
- 获取响应数据
- 数据解析
- 持久化存储
常用的数据解析方式包括:
正则匹配、bs4、XPath(常用)、PyQuery等。
1.1.3 数据解析原理
- html的主要作用是数据展示。
- 待解析的数据其实都存储在html标签之中或标签的属性中。
- 通用原理:
(1) 定位标签;
(2) 获取标签中的数据或者标签的属性值。
1.2 bs4解析
1.2.1 bs4数据解析步骤
- 实例化BeautifulSoup对象,将被解析的页面数据加载到BeautifulSoup对象中;
- 调用BeautifulSoup对象中的方法和属性,进行标签定位和相关数据的提取。
1.2.2 实例化BeautifulSoup对象
方式1:BeautifulSoup(fp, 'lxml')
用于对本地存储的html文件进行数据解析;
方式2:BeautifulSoup(page_text, 'lxml')
用于对互联网上请求到的页面资源进行数据解析。
解析器一般选用lxml
。
1.2.3 标签定位
标签定位
bs_obj.tagName
定位到第一次出现的指定标签。属性定位
bs_obj.find('tagName', attrName='attrValue')
find只可以定位到第一次出现的指定标签。bs_obj.find_all('tagName', attrName='attrValue')
find_all可以定位到符合条件的所有标签,返回值类型是列表。选择器定位
bs_obj.select('选择器')
id选择器、类选择器、层级选择器
注:层级选择器中
大于号:表示相邻层级
空格:表示中间间隔多个层级
fp = open('./test.html', 'r', encoding='utf-8')
bs_obj = BeautifulSoup(fp, 'lxml') # 实例化BeautifulSoup对象# 标签定位
bs_obj.div # 第一次出现的div标签
bs_obj.find('div', class_="song")
bs_obj.find_all('div', class_='song')
bs_obj.find_all('a', id='feng')bs_obj.select('#feng') # id选择器
bs_obj.select('.song') # 类选择器
bs_obj.select('.tang > ul > li > a') # 层级选择器
bs_obj.select('.tang a')
1.2.4 提取数据
取文本
tag.string: 获取标签直系的文本内容
tag.text: 获取标签下所有的文本内容取属性
tag['attrName']
bs_obj.find('a', id="feng").text
bs_obj.find('a', id="feng").stringbs_obj.find('a', id="feng")['href']
1.2.5 案例 爬取文学名著
目标:从诗词名句网爬取《三国演义》
《三国演义》:http://www.shicimingju.com/book/sanguoyanyi.html
import requests
from bs4 import BeautifulSoupheaders = {'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}
catalogue_url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
catalogue_text = requests.get(url=catalogue_url, headers=headers).text# 解析各章节标题 + 详情页的url
catalogue_bs_obj = BeautifulSoup(catalogue_text, 'lxml')
a_list = catalogue_bs_obj.select('.book-mulu > ul > li > a')
for each_a in a_list:each_title = each_a.stringeach_detail_url = 'http://www.shicimingju.com' + each_a['href']each_detail_text = requests.get(url=each_detail_url, headers=headers).text# 解析各章节的内容each_detail_bs_obj = BeautifulSoup(each_detail_text, 'lxml')each_detail_content = each_detail_bs_obj.find('div', class_='chapter_content').texteach_filepath = './sgyy/{title}.txt'.format(title=each_title)with open(each_filepath, 'w', encoding='utf-8') as fp:fp.write(each_detail_content)print('《{title}》下载保存成功!'.format(title=each_title))
1.3 XPath解析
1.3.1 XPath数据解析步骤
html标签是基于树状结构的。
- 实例化etree对象,将待解析的数据加载到该对象中;
- 调用etree对象中的xpath方法,结合着不同形式的xpath表达式进行标签定位和数据提取。
1.3.2 实例化etree对象
方式1:etree.parse('filename')
用于对本地存储的数据进行解析。
方式2:etree.HTML('page_text')
用于对互联网上请求到的页面资源进行数据解析。
1.3.3 标签定位
tree_obj.xpath(xpath表达式)
返回的数据类型是列表。
标签定位
对于最左侧的`/`,一定要从根标签开始定位;
对于最左侧的`//`,可以从任意位置的标签开始定位;
对于非最左侧的`/`,表示相邻层级;
对于非最左侧的`//`,表示中间间隔多个层级。属性定位
tree_obj.xpath('//tagName[@attrName="attrValue"]')索引定位
tree_obj.xpath('//tagName[index]')
注意索引从1开始,返回值类型仍是列表。模糊定位
tree_obj.xpath('//tagName[contains(@attrName, "attrValue")]')
tree_obj.xpath('//tagName[starts-with(@attrName, "attrValue")]')
from lxml import etreetree_obj = etree.parse('./test.html')
# 定位title标签
tree_obj.xpath('/html/head/title') # [<Element title at 0x...>]
tree_obj.xpath('/html//title')
tree_obj.xpath('//title')# 属性定位
tree_obj.xpath('//div[@class="song"]')# 索引定位
tree_obj.xpath('//div[2]')# 模糊定位
tree_obj.xpath('//div[contains(@class, "ng")]')
tree_obj.xpath('//div[starts-with(@class, "ta")]')
1.3.4 数据提取
取文本
/text():用于将标签中直系的文本内容取出,返回的列表只有一个元素;
//text():用于将标签中所有的文本内容取出;
tree_obj.xpath('//a[@id="feng"]/text()')
# ['凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘']
tree_obj.xpath('//a[@id="feng"]/text()')[0]
# '凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘'tree_obj.xpath('//div[2]//text()')
# ['\n\t\t', '李清照', '\n\t\t', '王安石', '\n\t\t'...]
''.join(tree_obj.xpath('//div[2]//text()'))
# '\n\t\t李清照\n\t\t王安石\n\t\t...'
取属性
/@attrName
tree_obj.xpath('//a[@id="feng"]/@href')
# ['http://www.haha.com']
1.3.5 案例 爬取糗事百科的段子
糗事百科的段子:https://www.qiushibaike.com/text/
爬取首页
import requests
from lxml import etreeheaders = {'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}
main_url = 'https://www.qiushibaike.com/text/'
main_text = requests.get(url=main_url, headers=headers).texttree_obj = etree.HTML(main_text)
# 标签定位
div_list = tree_obj.xpath('//div[@class="col1 old-style-col1"]/div')
for each_div in div_list:# 局部数据解析,从每一个div中进一步进行数据解析author_str = each_div.xpath('./div[1]/a[2]/h2/text()')[0] # ./指的是xpath方法的调用者content_list = each_div.xpath('./a[1]/div/span//text()')content_str = ''.join(content_list)print(author_str, content_str)
爬取指定页数
使用url模板:url_model = 'https://www.qiushibaike.com/text/page/%d/'
import requests
from lxml import etreeheaders = {'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}url_model = 'https://www.qiushibaike.com/text/page/%d/'
for each_page_num in range(1, 4):each_url = format(url_model % each_page_num)# main_url = 'https://www.qiushibaike.com/text/'each_text = requests.get(url=each_url, headers=headers).texttree_obj = etree.HTML(each_text)# 标签定位div_list = tree_obj.xpath('//div[@class="col1 old-style-col1"]/div')for each_div in div_list:# 局部数据解析,从每一个div中进一步进行数据解析author_str = each_div.xpath('./div[1]/a[2]/h2/text()')[0] # ./指的是xpath方法的调用者content_list = each_div.xpath('./a[1]/div/span//text()')content_str = ''.join(content_list)print(author_str, content_str)
扩展:可以使用百度AI进行语音合成。
百度AI在线语音合成:https://ai.baidu.com/tech/speech/tts_online
技术文档:https://ai.baidu.com/ai-doc/SPEECH/Ik4nlz8l6
1.3.6 案例 爬取彼岸图网的4K动漫图片
彼岸图网的4K动漫图片:http://pic.netbian.com/4kdongman/
import requests
import os
from lxml import etreedirname = './imgs'
if not os.path.exists(dirname):os.mkdir(dirname)headers = {'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}
url_model = 'http://pic.netbian.com/4kdongman/index_%d.html'
for each_page_num in range(1, 6):if each_page_num == 1:each_url = 'http://pic.netbian.com/4kdongman/'else:each_url = format(url_model % each_page_num)each_response_obj = requests.get(url=each_url, headers=headers)each_response_obj.encoding = 'gbk'each_page_text = each_response_obj.texttree_obj = etree.HTML(each_page_text)# tree_obj.xpath('//*[@id="main"]/div[3]/ul/li') # Copy XPathli_list = tree_obj.xpath('/html/body/div[2]/div/div[3]/ul/li') # Copy full XPathfor each_li in li_list:each_title_str = each_li.xpath('./a/img/@alt')[0]each_img_name = '{filename}.jpg'.format(filename=each_title_str)each_img_src = each_li.xpath('./a/img/@src')[0]each_img_url = 'http://pic.netbian.com/{each_img_src}'.format(each_img_src=each_img_src)each_img_data = requests.get(url=each_img_url, headers=headers).contenteach_img_path = '{dirname}/{each_img_name}'.format(dirname=dirname, each_img_name=each_img_name)with open(each_img_path, 'wb') as fp:fp.write(each_img_data)print('{each_img_name} 已下载。'.format(each_img_name=each_img_name))
1.3.7 与bs4的对比
如果需要解析出带有标签名的文本,需要使用bs4。
2 反爬机制与反反爬策略
2.1 robots协议
robots协议,也称为robots.txt,是存放于网站根目录下的ASCII编码格式的文本文件,用于告诉网络搜索引擎的漫游器本网站中的哪些内容不可以被漫游器获取,哪些内容是可以被漫游器获取的。
robots协议并不是一个规范,而只是约定俗成的,所以并不能保证网站的隐私。
举例:
https://www.bilibili.com/robots.txt
User-agent: *
Disallow: /include/
Disallow: /mylist/
Disallow: /member/
Disallow: /images/
Disallow: /ass/
Disallow: /getapi
Disallow: /search
Disallow: /account
Disallow: /badlist.html
Disallow: /m/
https://www.taobao.com/robots.txt
User-agent: Baiduspider
Disallow: /User-agent: baiduspider
Disallow: /
2.2 cookie反爬
案例:爬取雪球网中的资讯数据。
雪球网:https://xueqiu.com/
import requestsheaders = {'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}
target_url = 'https://xueqiu.com/statuses/hot/listV2.json'
params = {'since_id': '-1','max_id': '74012','size': '15',
}
response_obj = requests.get(url=target_url, headers=headers, params=params)
print(response_obj.json())
'''
{'error_description': '遇到错误,请刷新页面或者重新登录帐号后再试', 'error_uri': '/statuses/hot/listV2.json', 'error_data': None, 'error_code': '400016'}
'''
结果:爬取失败
解决方案:在headers中添加Cookie即可成功爬取数据。
在爬虫中处理Cookie的方式:
方式1:手动添加Cookie
利用抓包工具获取浏览器请求时携带的Cookie,将Cookie添加到headers字典中。
手动处理Cookie局限性:写入headers字典中的Cookie存在有效时长,会过期失效。
方式2:使用Session机制自动处理Cookie
获取一个Session对象,基于该Session对象进行请求发送。
在基于Session机制的请求响应过程中,如果服务器端产生了Cookie,会将Cookie自动保存到Session对象中。
如果Cookie被保存到Session对象中,则可以再次使用该Session对象发送请求,此次请求会自动携带Cookie。
import requestsheaders = {'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'
}# 创建Session对象。
session_obj = requests.Session()
# 使用Session对象向首页发送请求。
# 服务端产生Cookie,自动将Cookie保存于Session对象中。
main_url = 'https://xueqiu.com/'
session_obj.get(url=main_url, headers=headers)target_url = 'https://xueqiu.com/statuses/hot/listV2.json'
params = {'since_id': '-1','max_id': '74012','size': '15',
}
# 使用Session对象再次发送请求,此次请求中自动携带Cookie。
response_obj = session_obj.get(url=target_url, headers=headers, params=params)
print(response_obj.json())
2.3 代理反爬
代理指的是代理服务器,用于对请求或响应进行转发或拦截。
在反爬中使用代理的目的
如果使用爬虫在段时间内对一个网站发起一个高频请求,该网站会检测出这个异常的现象,并会获取异常请求ip,将ip加入到黑名单中,则该ip在近期无法再次对该网站进行网络访问。
如果本机ip被对方服务器加入到黑名单中,可以使用代理服务器进行请求转发,对方服务器获取的请求ip是代理服务器的ip,而不是本机的ip。
代理的匿名度
透明:对方服务器知道请求方使用了代理,也知道请求方的真实ip;
匿名:对方服务器知道请求方使用了代理,但是不知道请求方的真实ip;
高匿:对方服务器不知道请求方使用了代理,也不知道请求方的真实ip。
代理的类型
http:只支持转发http协议的请求;
https:只支持转发https协议的请求;
兼容http和https。
获取对方服务器收到的请求ip
未使用代理
target_url = 'https://www.sogou.com/web?query=ip'
page_text = requests.get(url=target_url, headers=headers).text
tree_obj = etree.HTML(page_text)
tree_obj.xpath('//*[@id="ipsearchresult"]//text()')
使用代理
target_url = 'https://www.sogou.com/web?query=ip'
page_text = requests.get(url=target_url, headers=headers, proxies={'https': '代理服务器ip:代理服务器port'}
).text
tree_obj = etree.HTML(page_text)
tree_obj.xpath('//*[@id="ipsearchresult"]//text()')
获取代理
全网代理IP(免费):http://www.goubanjia.com/
智连HTTP(付费):http://http.zhiliandaili.cn/
构建代理池
提取智连HTTP提供的代理服务器的ip + port的方法
import randomproxy_list = [] # 代理池
# url是在智连HTTP购买代理并提取后生成的API链接
url = 'http://ip.11jsq.com/index.php/api/entry?method=proxyServer.generate_api_url&packid=1&fa=0&fetch_key=&groupid=0&qty=51&time=1&pro=&city=&port=1&format=html&ss=5&css=&dt=1&specialTxt=3&specialJson=&usertype=2'
page_text = requests.get(url, headers=headers).text
tree_obj = etree.HTML(page_text)
data_list = tree_obj.xpath('//body//text()')
for each_data in data_list:https_dic = {}https_dic['https'] = each_dataproxy_list.append(https_dic)
使用代理池
url_model = 'http://www.521609.com/daxuemeinv/list8%d.html'
all_data_list = []
for each_page_num in range(1, 20):url = format(url_model % each_page_num)page_text = requests.get(url=url, headers=headers, proxies=random.choice(proxy_list) # proxy_list为上面构建的代理池).texttree_obj = etree.HTML(page_text)li_list = tree_obj.xpath('//*[@id="content"]/div[2]/div[2]/ul/li')for each_li in li_list:detail_url = 'http://www.521609.com' + each_li.xpath('./a[1]/@href')[0]page_detail_text = requests.get(url=detail_url, headers=headers,proxies=random.choice(proxy_list)).textall_data_list.append(page_detail_text)print(len(all_data_list))
2 爬虫 数据解析(bs4,XPath) robots协议 cookie反爬 代理反爬相关推荐
- 网络爬虫数据解析——BS4解析库
文章目录 简介 基本用法 BeautifulSoup选择器 节点选择器 方法选择器 CSS选择器 项目案例:基于requests和bs4的三国演义定向爬虫 简介 Beautiful Soup就是Pyt ...
- python爬虫循环表格xpath_python爬虫数据解析之xpath
xpath是一门在xml文档中查找信息的语言.xpath可以用来在xml文档中对元素和属性进行遍历. 在xpath中,有7中类型的节点,元素,属性,文本,命名空间,处理指令,注释及根节点. 节点 首先 ...
- python层级抓取_070.Python聚焦爬虫数据解析
一 聚焦爬虫数据解析 1.1 基本介绍 聚焦爬虫的编码流程 指定url 基于requests模块发起请求 获取响应对象中的数据 数据解析 进行持久化存储 如何实现数据解析 三种数据解析方式 正则表达式 ...
- 爬虫数据解析的三方式
2.爬虫数据解析的三方式 一.正则表达式解析 常用正则表达式回顾: 单字符:. : 除换行以外所有字符[] :[aoe] [a-w] 匹配集合中任意一个字符\d :数字 [0-9]\D : 非数字\w ...
- 网络爬虫信息提取的常识和Robots协议
网络爬虫介绍 在浏览网站中,所能见到的数据可以通过爬虫程序保存下来. 网络爬虫,小规模可以爬取网页,大规模可以爬取网站,或一系列的网站,超大规模的像搜索引擎的这种难以完成,需要定制开发,爬取全网. 网 ...
- python爬虫数据解析总结
python爬虫数据解析总结 目录 python爬虫数据解析总结 1.概述 2.Xpath解析html数据 2.1.基本语法 1.查询语法 2.2.Xpath解析html数据 1.安装lxml库 2. ...
- python爬虫实战之旅( 第三章:数据解析(xpath法))
上接:第三章:数据解析(bs4法) 下接:第四章:验证码识别 1.xpath解析简介 最常用且最便捷高效的一种解析方式.通用性很好 xpath解析原理 实例化一个etree的对象,且需要将被解析的页面 ...
- python爬虫数据解析xpath解析详细讲解——附有详细案例
案例③由于时间流逝,网页爬取失效了 最近考研复试,增加一个案例,爬取985211学校,并以excel表格形式存储 文章目录 1.什么是xpath 是最常用的最广泛的数据解析方式 2.xpath解析原理 ...
- python爬虫—数据解析
1 requests库的深度应用 网页信息采集 import requestsif __name__=="__main__":url=""#将参数封装到字典中k ...
最新文章
- 前端开发之JavaScript基础篇一
- Android系统开发和性能优化——查漏补缺【建议收藏】
- 前端小纠结--集成gitflow和standard-version使用
- jQuery日期弹出选择框Datepicker效果
- VTK修炼之道2_VTK体系结构1
- 云巡更系统 云设备巡检 电子云签到
- 基于3D模型的MaskRCNN的训练数据生成
- 【Drools一】值得打工人学习的规则引擎Drools
- RxJava学习(四利用RxJava打造自己的RxBus)
- 计算机管理 服务在哪,信息服务,教您哪里打开Internet信息服务(IIS)管理器
- H264___DCT蝶形算法____理解
- 概率与数理统计学习总结四---连续型随机变量及其概率密度
- 解决“可以联网后仍显示无法连接到Internet”
- 氨基-八聚乙二醇Amino-PEG8-alcohol,352439-37-3
- 超详细编写登录注册页面(内含验证码登录)
- G1垃圾回收器在并发场景调优
- C# WinForm 文件夹选择控件 folderBrowserDialog 的应用实例
- 遇到问题---CDH重启namenode--Command timed-out after 150 seconds--角色正在启动
- UVa 10074 - Take the Land
- Java版本 图书管理系统
热门文章
- Windows环境下个别Gem包安装不上的解决办法
- php停车场系统设计,基于PHP的停车场管理系统设计与实现
- windows 创建虚拟网卡 修改MAC地址
- YbtOJ——递推算法【例题4】传球游戏
- ABLIC Inc.推出具有宽工作电压范围的汽车用零点漂移运算放大器S-19630AB
- 建筑工地数字化监管和科学战疫的智慧力量
- Esp8266 ROTS SDK 编译示例 hello_world
- 利用IP地址获取用户的地理位置信息
- 关于JDBC连接MySQL的时候出现警告:Establishing SSL connection without server‘s identity verification is not recom
- ng-zorro中表格树的动态添加、修改、删除节点操作