网页爬虫抓取百度图片(一张前端与反爬虫这一的区别)
优采云 发布时间: 2022-02-06 21:23网页爬虫抓取百度图片(一张前端与反爬虫这一的区别)
[目录]
1. 前言
对于一个网页,我们往往希望它结构合理,内容清晰,以便搜索引擎能够准确识别。另一方面,还有一些我们不希望内容被轻易获取的场景,比如电商的交易量网站、教育话题网站等。因为这些内容往往是产品的命脉,必须得到有效保护。这就是爬行动物和反爬行动物的话题的由来。爬取图片的整体操作流程可以分为三个步骤:
获取页面信息 读取图片链接并将图片保存在本地指定目录
2. 常见的反爬虫策略
但是世界上没有可以完美反爬虫的网站。
如果页面想要在不给爬虫机会的情况下正常显示在用户面前,它必须能够识别真人和机器人。因此,工程师们进行了各种尝试。这些策略大多用在后端,也是目前比较常规有效的手段,比如:
而爬行动物可以无限接近真人,比如:
所以我们说,100% 反爬策略?不存在的。这更像是一种体力活动,这是一个困难的问题。
不过作为前端工程师,我们可以增加游戏的难度,设计一些非常(sang)有意义(bing)思维(kuang)**的反爬虫策略。
3.前端和反爬虫3.1 FONT-FACE拼凑
示例:猫眼电影
在猫眼电影中,票房数据并不是纯粹的数字。页面使用font-face定义字符集,使用unicode映射显示。也就是说,除了图像识别,还要同时爬取字符集才能识别数字。
而且,每次页面刷新,字符集的url都会发生变化,这无疑增加了爬取成本,难度更大。
3.2 背景拼凑
例子:
与字体的策略类似,美团使用背景拼凑。数字实际上是图片,根据不同的背景偏移量显示不同的字符。
而不同的页面,图片的字符排序也不同。但是理论上只需要生成0-9和一个小数点,所以不明白为什么会有重复的字符。
3.3 个字符穿插
示例:微信公众号文章
一些微信公众号的文章中穿插着各种神秘的人物,这些人物都是通过样式隐藏起来的。这种方法虽然令人震惊……但其实识别过滤也不是太难,甚至可以做得更好,但也是一种脑洞。
3.4 伪元素隐藏
示例:汽车主页
汽车之家,关键制造商信息被放入伪元素的内容中。这也是一种思路:爬取网页,必须解析CSS,获取伪元素的内容,增加了爬虫的难度。
3.5 元素定位叠加
示例:去哪里
数学爱好者在哪里?对于一个4位数的票价,先用四个i标签渲染,然后用两个b标签进行绝对定位偏移,覆盖故意显示错误的i标签,最后在视觉上形成正确的价格……
这说明爬虫无法解析CSS,必须做数学题。
3.6 IFRAME 异步加载
例子:
打开网易云音乐页面时,html源码中几乎只有一个iframe,其src为空:about:blank。然后js开始运行,整个页面的frame异步塞进iframe中……
不过这种方式带来的难度并不大,只是在异步和iframe处理上走了弯路(或者还有其他原因,不完全基于反爬的考虑),不管你用selenium还是phantom,都有API可用于 iframe 中的内容信息。
3.7 个字符分割
示例:全网代理IP
在一些显示代理IP信息的页面上,IP的保护也很麻烦。
他们会先将 IP 号和符号划分为 dom 节点,然后在中间插入混淆数字。如果爬虫不知道这个策略,就会认为自己成功获取了值;但如果爬虫注意到,它就会被解决。.
3.8 个字符集替换
示例:去哪里移动边
移动版去哪儿也会欺骗爬虫。
3211明明写在html里,但是1233是直观显示的。原来他们重新定义了字符集,3和1的顺序刚好互换了结果……
4.示例:爬取百度图库
import re
import os
import time
import requests
# from selenium import webdriver
#########################
###此段代码不需要关心啥意思###
#########################
if not os.path.exists('百度图片'):
os.mkdir('百度图片')
#####################
###限制30张图片的代码###
####################
# 获取所有图片
response = requests.get(
'http://image.baidu.com/search/index?ct=201326592&cl=2&st=-1&lm=-1&nc=1&ie=utf-8&tn=baiduimage&ipn=r&rps=1&pv=&fm=rs7&word=风景')
data = response.text
img_desc_dics = re.findall("app.setData(\('imgData.*?\));", data, re.S)[0]
img_desc_dics = eval(str(img_desc_dics))
# 获取所有图片的数据
img_datas = img_desc_dics[1]['data']
count = 0
for img_data in img_datas:
# 获取搜索图片的参数
os_ = img_data.get('os')
cs_ = img_data.get('cs')
if os_ and cs_:
# 获取搜索图片的信息
img_search_url = f'http://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E9%A3%8E%E6%99%AF&step_word=&hs=0&pn=1&spn=0&di=195030&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=-1&cs={cs_}&os={os_}'
img_search_response = requests.get(img_search_url)
img_search_data = img_search_response.text
# 获取图片信息
img_url = re.findall('''\('firstSc'\);" src="(.*?)"''', img_search_data)[0]
img_name = img_url.split('/')[-1]
img_name = os.path.join('百度图片', img_name) # 拼接出图片的地址,如 百度图片/3822951_144045377000_2.jpg
# 保存图片
img_response = requests.get(img_url)
img_data = img_response.content
fw = open(img_name, 'wb')
fw.write(img_data)
fw.flush()
# 提示
count += 1
print(f'{img_name}保存成功,成功保存{count}张')
# 防止百度禁ip,慢一点
time.sleep(0.01)
#########################################################################
###自行百度selenium的用法,使用这一套代码可以无限爬取所有图片,否则将被限制30张###
## 记得加库哦
########################################################################
page_count_end = 2 # 爬取 指定数字(10)* 30 = 300张图片
chrome = webdriver.Chrome()
## 安装谷歌插件
##http://chromedriver.storage.googleapis.com/index.html?tdsourcetag=s_pcqq_aiomsg
## 查看你电脑的谷歌版本,寻找对应版本进行下载解压
try:
chrome.implicitly_wait(10)
chrome.get(
'http://image.baidu.com/search/index?ct=201326592&cl=2&st=-1&lm=-1&nc=1&ie=utf-8&tn=baiduimage&ipn=r&rps=1&pv=&fm=rs7&word=风景')
js_code = '''
window.scrollTo(0, document.body.scrollHeight);
var lenOfPage = document.body.scrollHeight;
return lenOfPage
'''
# selenium控制爬取页数
count = 0
page_count = 0
while page_count < page_count_end:
try:
page_count += 1
chrome.execute_script(js_code)
time.sleep(0.3)
except:
continue
img_desc_search_urls = re.findall('href="(/search/detail\?.*?)"', chrome.page_source, re.S) # re.S使.可以匹配换行符
# 获取所有图片的数据
for img_data in img_desc_search_urls:
try:
# 获取搜索图片的参数
os_ = re.findall('os=(.*?)&', img_data)[0]
cs_ = re.findall('cs=(.*?)&', img_data)[0]
if os_ and cs_:
# 获取搜索图片的信息
img_search_url = f'http://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E9%A3%8E%E6%99%AF&step_word=&hs=0&pn=1&spn=0&di=195030&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=-1&cs={cs_}&os={os_}'
img_search_response = requests.get(img_search_url)
img_search_data = img_search_response.text
# 获取图片信息
img_url = re.findall('''\('firstSc'\);" src="(.*?)"''', img_search_data)[0]
img_name = img_url.split('/')[-1]
img_name = os.path.join('百度图片', img_name) # 拼接出图片的地址,如 百度图片/3822951_144045377000_2.jpg
# 保存图片
img_response = requests.get(img_url)
img_data = img_response.content
fw = open(img_name, 'wb')
fw.write(img_data)
fw.flush()
# 提示
count += 1
print(f'{img_name}保存成功,成功保存{count}张')
# 防止百度禁ip,慢一点
time.sleep(0.01)
except:
continue
except Exception:
pass
finally:
chrome.close()
结果
由于百度的反爬措施是不断更新的,如果过了一段时间还想爬,就需要寻找新的规则
5.总结
对于每个 网站 爬行,都有一定的规则。每一个网站,尤其是大的网站,都在定期排版。做爬虫,必须注意细节,慎重决策。对于成败,找到你需要的文字、图片,或者视频、文件等,找到它们的链接,进行多重分析,耐心找出规律,这是你成功的关键。