爬虫笔记3
设置日志
import logging
# 设置日志输出样式
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',datefmt='%a, %d %b %Y %H:%M:%S',filename='log.log',filemode='a')
logger = logging.getLogger(__name__)
logger.warning('hello python')
获得QQ音乐链接
# 一般是下载的网址前缀+音乐ID = 下载音乐的直达链接
# QQ音乐的音乐ID表示为:media_mid = '002jNyoG3FhJQt'
def get_qqmusic_href():
url = 'https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=%E9%80%81%E4%BD%A0%E4%B8%80%E6%9C%B5%E5%B0%8F%E7%BA%A2%E8%8A%B1'
driver = webdriver.Chrome()
driver.get(url)
# 代码的运行速度要比浏览器加载速度快
# 如果我进入网页,数据没有加载出来,不能获取到数据
# 可以使用time.sleep(3)强制等待
# 但是selenium有一个更智能的隐式等待
# 3s之内元素加载完成即可,即此时的3s代表最长等待时间
driver.implicitly_wait(3)
# .get_attribute('href'):获取a标签的href属性,selenium语法和xpath语法不一样
href = driver.find_element_by_xpath('//span[@class="songlist__songname_txt"]/a').get_attribute('href')
return href
分析爬取音乐步骤
1.数据从哪里来?从服务器来,从网站上的服务器上下载的
2.怎么从网址里得到音乐?向这个网站发起网络数据的请求
3.筛选音乐文件
4.下载音乐文件
tips:两个html嵌套,也是反爬的一种机制
1爬取豆瓣电影排行榜
url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=200'
# 返回的是json格式数据,使用json()方法即可转为python列表或字典形式
text = response.json()
2爬取肯德基餐厅位置查询数据
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
"""分析
# 1.在录入关键字的文本框中录入关键字按下搜索,发起的是一个ajax请求,地址栏url没变
# 2.当前页面刷新出来的位置信息一定是通过ajax请求请求到的数据
# 3.基于抓包工具定位到该ajax请求的数据包,从该数据包中捕获数据:请求url、请求方式、请求携带的参数"""
data = {
'cname': '',
'pid': '',
'keyword': '北京',
'pageIndex': '1',#显示的页码
'pageSize': '80',#每页显示条数
}
3化妆品生产许可信息管理系统服务平台企业名单
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
练习xpath解析
# 三国演义章节内容爬取
url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
# 高清4k美女图片爬取,保存图片
url = 'https://pic.netbian.com/4kmeinv/'
# 空气质量历史数据查询,拿城市名称
url = 'https://www.aqistudy.cn/historydata/'
# 站长素材,亚洲美女图片爬取
url = 'https://sc.chinaz.com/tag_tupian/YaZhouMeiNv.html'#有js动态加载,懒加载反爬
# 站长素材,简历模板爬取
url = 'https://sc.chinaz.com/jianli/yingjiesheng.html'
"""
分析:判定爬取的资讯数据是否为动态加载
更多的资讯数据,是动态加载的,当鼠标滚轮滑动时,会捕获到更多数据
使用全局搜索或局部搜索定位到ajax请求的数据包,提取对应的url响应数据为json形式的资讯数据
"""
# 将最热板块下爬取梨视频下对应的小视频
url = 'https://www.pearvideo.com/'
# 党史记
url = 'http://cpc.people.com.cn/GB/64184/64190/65724/index.html'
# 国家企业信用信息公示系统
url = 'http://www.gsxt.gov.cn/corp-query-homepage.html'
# 开发文章爬取
url = 'https://toutiao.io/'
Session存储cookie
# 雪球网的咨询信息
# 经测试,一般情况下headers中只有Cookie和User-Agent是必须的,有时需要带上referer
session = requests.Session()#创建好了session对象
# 第一次使用session捕获且存储cookie
# 猜测第一次请求首页的时候就可能会产生cookie
main_url = 'https://xueqiu.com'
session.get(main_url,headers=headers)#捕获并且存储cookie
url = 'https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=185618&size=15'
page_text = session.get(url,headers=headers).json()#携带cookie发起的请求
print(page_text)
# 也可能是针对其他页面发起请求得到的cookie,要具体分析
# 代理操作
# xpath解析不能出现tbody标签
pathlib使用方法
from pathlib import Path
f = Path('code.jpg')#code.jpg#<class 'pathlib.WindowsPath'>
f.write_bytes(data)#无追加模式
f = Path('readme.txt')
res = f.read_text(encoding='utf-8')
selenium滑动操作
from selenium import webdriver
from time import sleep
url = 'https://www.jd.com'
driver = webdriver.Chrome()#若环境变量里有浏览器驱动,则不用加excutable_path
driver.get(url)
# 标签定位
search = driver.find_element_by_xpath('//*[@id="key"]')
search.send_keys('干脆面')
btn = driver.find_element_by_xpath('//*[@id="search"]/div/div[2]/button')
btn.click()
sleep(2)
# 在搜索页面进行滚轮向下滑动的操作(执行js操作:js注入)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
sleep(5)
driver.quit()
国家药品监督管理局化妆品生产许可信息爬取
url = 'http://scxk.nmpa.gov.cn:81/xk/'
driver = webdriver.Chrome()
driver.get(url)
sleep(1)
page_text_list = []#装所有页面的源码数据
page_text_list.append(driver.page_source)#先装第一页源码数据
# 点击下一页
for i in range(2):
driver.find_element_by_xpath('//*[@id="pageIto_next"]').click()
sleep(1)
page_text_list.append(driver.page_source)
driver.quit()
# 解析每一页数据
for page_text in page_text_list:
html = etree.HTML(page_text)
li_list = html.xpath('//*[@id="gzlist"]/li')
print(len(li_list))
for li in li_list:
name = li.xpath('./dl/@title')[0]
print(name)
爬虫小技巧
1.不要执着于PC端,试试爬取手机端
2.反爬虫的原因之一就是怕服务器撑不住,那凌晨3点爬取好了
3.善用别人的User-Agent,看看robots.txt,一般为域名加上/robots.txt即可查看,看它允许什么样的请求头爬取
4.查看网站所有的url,域名加上/sitemap.xml访问,注意有的网站是没有的
网页分析
- 有页码的,刷新看看,url有没有变化,没变化的是ajax请求,动态加载。
多点几次页码请求,对比分析几次相同开头的请求,进入请求头查看具体数据接口。 - 甄别网页是否为js动态渲染,安装谷歌插件Toggle JavaScript。
或者打开DevTools,右上角,设置,首选项,Debugger,Disable JaveScript。
tips:VIP视频、音乐不能看、不能听,其实只要在网址前面加上wn.run/回车即可观看
tips:先指定响应的编码格式,再以相同的编码格式写入文件,即可解决乱码问题
response.encoding = 'utf-8'
动态加载数据
有些数据是通过非浏览器地址栏中的url请求到的数据,而是其他请求请求到的数据,
那么这些通过其他请求请求到的数据就是动态加载的数据。
如果数据为动态加载,那么我们如何捕获到动态加载的数据?
基于抓包工具进行全局搜索,定位到动态加载数据对应的数据包,提取
# 返回的是json格式数据,使用json()方法即可转为python列表或字典形式
response.json()
基于抓包工具进行全局搜索不一定可以每次都搜索定位到动态加载数据对应的数据包?
如果动态加载的数据是经过加密的密文数据。
图片懒加载反爬
不在浏览器可视化范围内的,不会加载,此时源码中是伪属性
此时通过requests模块请求,但requests模块是没有可视化范围的,意味着所有的都是伪属性
请求伪属性,便可拿到图片数据。图片懒加载广泛应用在一些图片的网站中。
robots、UA伪装、动态加载数据的捕获、图片懒加载
今日内容
cookie、代理机制、验证码的识别、模拟登录
- cookie:是存储在客户端的一组键值对。
- web中cookie的典型应用:免密登录
- cookie和爬虫之间的关联:
有时对一张页面请求的时候,如果请求的过程中不携带cookie的话,那么我们是无法请求到正确的页面数据。
因此cookie是爬虫中一个非常典型且常见的反爬机制。
雪球网的咨询信息
url = 'https://xueqiu.com'
"""
分析:判定爬取的资讯数据是否为动态加载
更多的资讯数据,是动态加载的,当鼠标滚轮滑动时,会捕获到更多数据
使用全局搜索或局部搜索定位到ajax请求的数据包,提取对应的url响应数据为json形式的资讯数据
"""
{
'error_description':'遇到错误,请刷新页面或者重新登录帐号后再试',
'error_uri':'/statuses/hot/listV2.json',
'error_data':None,
'error_code':'400016'
}
"""
问题:我们没有请求到想要的数据
原因:没有严格意义上模拟浏览器发请求
处理:可以将浏览器发请求携带的请求头,全部粘贴在headers字典中,将headers作用到requests请求操作中即可
"""
cookie的处理方式
1.手动处理
弊端:cookie如果过了有效时长则该方式失效
将抓包工具中的cookie粘贴到headers中
2.自动处理
基于Session对象实现自动处理
- 如何获取一个session对象:requests.Session()返回一个session对象
- session对象的作用:
1.该对象可以像requests一样调用get和post方法发起指定的请求。只不过如果在使用session发请求的过程中如果产生了cookie,则会被自动存储到该session对象中,那么就意味着下次再次使用session对象发起请求,则该次请求就是携带cookie进行的请求发送。
2.在爬虫中使用session的时候,session对象至少会被使用几次?
两次。第一次使用session是为了将cookie捕获且存储到session对象中。下次的时候就是携带了cookie进行的请求发送。
session = requests.Session()#创建好了session对象
# 第一次使用session捕获且存储cookie
# 猜测第一次请求首页的时候就可能会产生cookie
main_url = 'https://xueqiu.com'
session.get(main_url,headers=headers)#捕获并且存储cookie
url = 'https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=185618&size=15'
page_text = session.get(url,headers=headers).json()#携带cookie发起的请求
print(page_text)
代理操作
-
在爬虫中,所谓的代理指的是什么?
就是代理服务器 -
代理服务器的作用是什么?
就是用来转发请求和响应 -
在爬虫中为什么需要使用代理服务器?
如果我们的爬虫在短时间内对服务器发起了高平的请求,那么服务器端会检测到这样的异常请求行为,
就会将该请求对应的设备IP禁掉,就意味着客户端设备无法对服务器端再次进行进行请求发送。(IP被禁掉了)如果IP被禁掉,我们就可以使用代理服务器进行请求转发,破解IP被禁的反爬机制,因为使用代理后,服务器端接收到的请求对应的IP地址就是代理服务器而不是我们真正的客户端的。
- 什么类型的代理只能转发对应类型的请求。推荐使用代理精灵
- 代理池就是一个代理列表
使用代理机制破解IP被封的效果
被封会显示该网页无法正常工作,目前无法处理此请求,HTTP ERROR 503
验证码的识别
基于线上的打码平台识别验证码:超级鹰、云打码、打码兔
-
使用步骤
1.注册:用户中心的身份
2.登录:用户中心的身份- 查询余额,不足请充值;
- 创建一个软件ID;
- 下载示例代码。
-
模拟登录流程
- 对点击登录按钮对应的url发送请求(post请求)
- 处理请求参数:用户名、密码、验证码、其他防伪参数
from pathlib import Path
f = Path('code.jpg')#code.jpg#<class 'pathlib.WindowsPath'>
f.write_bytes(img_data)#无追加模式
f = Path('readme.txt')
data = f.read_text(encoding='utf-8')
模拟登录失败了
可能的原因:
- cookie
所以将所有请求都用session发送请求,不知道是哪个请求产生了cookie。
在请求参数中如果看到了一组乱序的请求参数,最好去验证这组请求参数是否为动态变化。
若为动态变化,有两种常用处理方式:- 方式1:一般来讲动态变化的参数会被隐藏在前台页面中,那么我们就要去前台页面源码中找。
- 方式2:如果前台页面中没有的话,我们就可以基于抓包工具进行全局搜索
基于百度AI实现的爬虫功能
- 图像识别
- 语音识别&合成
- 自然语言处理
使用流程:电机控制台进行登录
选择想要的功能、实现功能下创建一个app、选择对应的pythonSDK文档进行代码实现
selenium使用
如果通过find系列的函数进行标签定位,如果标签是存在于iframe下面,则会定位失败,
解决方案:使用switch_to即可
driver.switch_to.frame('iframe的id')
如何让selenium规避检测
-
有的网站会检测请求是否为selenium发起,如果是的话则让该次请求失败
-
规避检测的方法:
-
selenium接管chrome浏览器
我们可以利用Chrome DevTools协议。它允许用户检查和调试Chrome浏览器。打开cmd,键入命令:chrome.exe --remote-debugging-port=9222 --user-data-dir="G:NewChrome"
-
-
对于-remote-debugging-port值,可以指定任何打开的窗口
-
对于-user-data-dir标记,指定创建新Chrome配置文件的目录,它是为了确保在单独的配置文件中启动chrome,不会污染你的默认配置文件
-
还有不要忘了在环境变量中PATH里将chrome的路径添加进去
-
此时会打开一个浏览器页面,输入网址,就可以把它当成一个已经存在的浏览器
实现步骤
-
1.必须将电脑中安装的谷歌浏览器的驱动程序所在目录找到,并将目录添加到环境变量中。
-
2.打开cmd,键入命令:
chrome.exe --remote-debugging-port=9222 --user-data-dir="自定义的一个空文件夹目录,在哪都行"
指定执行结束后,会打开你本机安装好的谷歌浏览器
-
3.执行如下代码,就可以使用下面的代码接管步骤2打开的真实浏览器
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
opt = Options()
opt.add_experimental_option('debuggerAddress', '127.0.0.1:9222')
driver = webdriver.Chrome(executable_path='C:Program Files (x86)GoogleChromeApplicationchromedriver.exe', chrome_options=opt)
print(driver.title)
由于PhantomJs最近已经停止了更新和维护,所以推荐大家使用谷歌的无头浏览器
opt.add_argument('--headless')
opt.add_argument('--disable-gpu')
12306验证码图片截取并保存
from selenium import webdriver
from time import sleep
from PIL import Image
driver = webdriver.Chrome()
driver.get(url)
sleep(1)
# 保存包含验证码的截图
driver.save_screenshot('screenshot.png')#如果能截图下来,说明加载到数据
# 确定验证码图片对应的左上角和右下角的坐标(裁剪区域就确定了)
ele = driver.find_element_by_xpath('')
loc = ele.location#验证码图片左上角的坐标x,y{'x': 366, 'y': 293}
size = ele.size#验证码标签对应的长和宽{'height': 190, 'width': 293}
# 确定裁剪区域
range = (int(loc['x']), int(loc['y']), int(loc['x']+size['width']), int(loc['y']+size['height']))
i = Image.open('screenshot.png')
# 根据指定区域进行图片裁剪
i.crop(range).save('code.png')
# 将验证码图片提交给打码平台,如超级鹰,获得返回的结果坐标,使用selenium进行模拟点击即可
涉及到的相关内容
- js中常见的加密算法剖析
- 线性散列MD5算法
- 对称加密DES/AES算法
- 非对称加密算法RSA
- base64伪加密
- https证书密钥加密
可以处理的爬虫问题
模拟登录中密码加密和其他请求参数加密处理
动态加载且加密数据的捕获和破解
重点:找寻到js算法加密和解密相关流程的编码处理套路/技巧,大幅度提升处理相关问题的效率
# chrome://welcome/
# chrome://welcome/new-user
微信公众平台
1、登录时,可先输入一个错误的密码,抓包,
2、如何查看是否是登录所对应的数据包,查看表单数据有没有账号和密码
3、pwd:密码,838ece1033bf7c7468e873e79ba2a3ec
,32位,16进制,猜测为md5加密;
4、查找定位对应的pwd的js代码,搜索技巧:由于需要给对应的关键字赋值,所以可以搜索password:
或者password=
或者password =
浏览器自带的抓包工具,按Ctrl+F出来的搜索框,不能打断点
所以使用右上角的三点中的search,输入关键字,查找对应的js文件中对应的加密函数,
进入js文件,打上断点,将光标选中对应的代码即可查看对应的结果
一般选择目标函数外层大括号内的代码即可满足调用要求,若遇到相关变量的缺失,一般给其定义
为空字典即可。
5、js调试工具:发条调试工具
6、python模拟执行js代码
1.nodejs开发环境
2.pip install PyExecJs
# RSA:非对称密钥加密
url = 'https://store.steampowered.com/login/'
# 凡科:闭包
url = 'https://i.fkw.com/'
tips:如果需要逆向的js函数的实现是出现在一个闭包中,那么直接将闭包的整个代码块拷贝出进行调试即可。