站长素材图片数据的爬取(正则表达式):
老规矩:先判断页面数据是否是ajax生成,在局部搜索发现不是动态加载的数据。
接着看发现,虽然没有ajax,但站长素材用了图片懒加载,也是一种反爬机制:
图片懒加载是什么意思呢,就是不在用户可视化范围内的图片前端src标签统统是src2,当然这个可以不是src2自定义名称也行,src2肯定是不能发起请求显示图片的,当用户滚轮往下滑动,一旦图片进去了用户可视化范围内,前端js就会动态的把src2换成src,就达到了显示图片的效果,这就叫做图片懒加载。
首先已经知道不是ajax动态生成数据,是当前请求url上确确实实存在的,只用了图片懒加载。这其实也是一种反爬机制,用伪属性,不认真分析网页你直接抓常规的src是抓不到的,只能抓到当前页面可视化的图片url。
<a target="_blank" href="http://sc.chinaz.com/tupian/200409136340.htm" alt="印度装美女头像图片">
<img src2="http://pic.sc.chinaz.com/Files/pic/pic9/202004/zzpic24295_s.jpg" alt="印度装美女头像图片">
</a>
所以我们现在的任务是提取出src2的内容,不能直接定位img标签下的src2,这样有可能把懒加载的广告图片的地址也抓下来,我们从a标签开始定位,如果还不行就从再上一级的div开始定位,你不用正则用其他解析方式也可以。
import re
url = 'http://sc.chinaz.com/tupian/'
response_str = requests.get(url,headers=headers).content.decode()
# 拿src2的正则表达式
ex = '<a.*?<img src2="(.*?)" alt.*?</a>'
# 只要是正则都加上re.S,可以处理前端源码的回车
imageurl_list = re.findall(ex,response_str,re.S)
print(imageurl_list)
接着就是遍历这个url列表来发请求,再追加保存到目录中就好了
面试题:爬取这个店面的详情数据。
https://m.vmall.com/help/hnrstoreaddr.htm
进入页面发现,该页面的所有门店都是ajax生成,马上找到了对应的请求包:
点进任意一个店面的详情页如下图,发现也是ajax动态生成的。在下图去全局抓包搜索,找到了动态请求而来的包。
在postman中模拟ajax的post请求详情页:
看了多个店面的详情页的这个ajax请求的参数后发现:只有shopId不一样
我们马上去首页全局搜这个107811的id,像前面搜药监局的ajax加密的请求参数一样,肯定会在全局找到一堆id串
但是发现这个装有所有门店id的请求包对应的请求体的数据是一个json数据:
它不是不是以前的的这样的:
果然,我还是直接data=data发现拿不到想要的店面的id,一个json串
data = {
"portal":2,
"lang":"zh-CN",
"country":"CN",
"brand":1,
"province":"四川",
"city":"成都",
"pageNo":1,
"pageSize":20,
}
shop_str= requests.post('https://openapi.vmall.com/mcp/offlineshop/getShopList',headers=headers,data=data).json()
print(shop_str)
结果:
于是我改了一下:改为json=或者序列化一下json
# 我还可以在这儿加个for pageNo in range(1,10),
# 就能爬前九页的店面id
data = {
"portal":2,
"lang":"zh-CN",
"country":"CN",
"brand":1,
"province":"四川",
"city":"成都",
"pageNo":1,
"pageSize":20,
}
# 或者这样也可以import json
# data=json.dumps(data)
shop_str= requests.post('https://openapi.vmall.com/mcp/offlineshop/getShopList',headers=headers,json=data).json()
shop_ids = list()
for dic in shop_str['shopInfos']:
shop_id = dic['id']
shop_ids.append(shop_id)
print(shop_ids)
现在拿到了要爬取页面的门店的所有id,并塞进了shop_ids列表里,然后就可以遍历这个列表,动态化参数id发ajax请求拿店面详情信息:
for _id in shop_ids:
url = 'https://openapi.vmall.com/mcp/offlineshop/getShopById'
params = {
"portal":2,
"version":10,
"country":"CN",
"shopId":_id,
"lang":"zh-CN",
}
print("正在抓取id为{}的店面信息".format(id))
shop_html = requests.get(url,headers=headers,params=params).json()
name = shop_html["shopInfo"]["name"]
address = shop_html["shopInfo"]["address"]
print(name+":"+address)
结果: