输入需要爬取商品品类的网址和需要爬取的页数,程序将爬取所有商品的链接
输入需要爬取商品品类的网址和需要爬取的页数,程序将爬取所有商品的链接
import time
from DrissionPage import ChromiumPage
import csv
from lxml import etree
import json
import os
# 确保存放数据的data文件夹存在,若不存在就创建
folder_path=r".\data"
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# 文件路径[保存]【多个商品链接数据】
file = r".\data\自动化天猫1.0.csv"
# 创建文件对象,用于保存数据
csv_file=open(file,mode='w',encoding='utf-8-sig',newline='')
# 字典写入的方法
csv_writer=csv.DictWriter(
csv_file,
fieldnames=['发货地','店名','商品','商品链接','页面价格']
)
# 写入表头
csv_writer.writeheader()
# 实例化浏览器对象
chrom=ChromiumPage()
# 监听数据包 https://h5api.m.taobao.com/h5/mtop.relationrecommend.wirelessrecommend.recommend/2.0/?
# 目的第一次登录可能需求手动登录,还有切换页面,若数据包一直没有出现,则会一直等待,直至数据包出现, 提高容错率
data_bag=f"https://h5api.m.taobao.com/h5/mtop.relationrecommend.wirelessrecommend.recommend/2.0/?"
chrom.listen.start(data_bag)
# 打开网页【首页】
# 之后手动切换需要的网页【第一次】
chrom.get('https://www.tmall.com/') # 天猫首页
print("如需求登录,请手动登陆!!!")
url=input("登陆完成后!!请输入需要爬取的网页:\n")
chrom.get(url)
print("成功跳转到:"+url)
all_page=int(input("请输入要采集的页数:\n"))
print(f"本次采集将爬取{all_page}页数据的商品链接!!!")
# 采集前20页数据
for page in range(1,all_page+1):
time.sleep(5) # 每爬取一页,休眠5秒,防止被反爬
print("开始爬取第{}页数据,准备开始请求!!!:".format(page))
# 等待数据包加载
# 在 DrissionPage 的监听功能中,默认情况下,chrom.listen.wait() 方法如果没有指定 timeout 参数,它会永久等待,直到捕获到目标数据包为止。
resp = chrom.listen.wait() # 第一次运行时,可能需要你手动登录, 登录完成后才能获取数据
print("获取到数据包!!!开始尝试解析!!!")
"""
在DrissionPage库的代码情境中,resp.response.body用于获取捕获到的数据包响应的内容主体。具体解释如下:
resp:它是通过chrom.listen.wait()获取到的数据包对象。这个对象包含了与捕获到的数据包相关的各种信息,如请求头、响应头、响应内容等。
response:resp对象的一个属性,用于访问该数据包的响应部分。响应部分包含了服务器返回给客户端的信息,比如状态码、响应头和响应体等。
body:response对象的属性,代表响应内容的主体部分。
对于 HTTP 请求来说,如果请求的是一个网页,body里可能是 HTML 内容;
如果请求的是 JSON 数据,body里就是 JSON 格式的字符串;
如果请求的是图片、视频等二进制文件,body里就是对应的二进制数据
"""
# 获取响应数据
response_data = resp.response.body
# print("处理前:")
# print(response_data)
# 检查response_data是否为字节类型。在网络请求中,从服务器获取的响应数据有时会以字节类型返回,而后续处理 JSON 数据需要字符串类型,所以需要进行检查和转换
if isinstance(response_data, bytes):
print("response_data是字节类型,使用decode('utf-8')方法将其解码为 UTF - 8 编码的字符串")
response_data = response_data.decode('utf-8')
try:
# 处理JSONP格式,去掉外层包裹
start_index = response_data.find('{') # 查找字符串response_data中第一个{的位置,这是 JSON 数据的起始位置
end_index = response_data.rfind('}') # 查找字符串response_data中最后一个}的位置,这是 JSON 数据的结束位置
# 通过切片操作,提取出完整的 JSON 字符串部分。
# 有些接口返回的数据可能是 JSONP 格式,即数据被包裹在一个函数调用中
# 例如mtopjsonp5({"key": "value"}),这一步是去除包裹部分,只保留 JSON 数据本身
json_str = response_data[start_index:end_index + 1]
response_json_data = json.loads(json_str) # 使用json.loads()函数将提取的 JSON 字符串转换为 Python 字典
# print("处理后:")
# print(response_json_data)
except json.JSONDecodeError as e:
print(f"解析JSON数据时出错: {e}")
goods=response_json_data['data']['itemsArray']
# 循环遍历每一个店铺数据
for good in goods:
good_data = {}
# 提取发货地
Shipping_Place = good.get('procity')
good_data['发货地'] = Shipping_Place if Shipping_Place else "无发货地"
# 提取店名
shop_name = good.get('nick')
good_data['店名'] = shop_name if shop_name else "无店名"
# 提取商品
Product = good.get('title')
good_data['商品'] = Product if Product else "无商品"
# # 提取商品链接
# Product_Link = good.get('clickUrl')
# good_data['商品链接'] = Product_Link if Product_Link else "无商品链接"
# 提取商品链接
Product_Link = good.get('auctionURL')
Product_Link = "https:" + Product_Link
good_data['商品链接'] = Product_Link if Product_Link else "无商品链接"
# 提取页面价格
Price = good.get('price')
good_data['页面价格'] = Price if Price else "无页面价格"
print(good_data)
# 写入数据
csv_writer.writerow(good_data)
print("第{}页数据爬取完成!!并成功写入csv文件!!准备点击下一页按钮!!".format(page))
# 爬完一页并写入csv文件后,点击下一页按钮
try:
# 检查是否存在“下一页”按钮
next_button = chrom.ele('xpath://*[@class="next-pagination-pages"]/button[2]')
if next_button: # 如果按钮存在
next_button.click() # 点击按钮
print("已成功点击下一页按钮!!准备获取下一页【next_page:{}】数据!!".format(page+1))
else:
print("没有找到下一页按钮,可能是最后一页")
except Exception as e:
print(f"点击下一页按钮时发生错误: {e}")