昨天临时接了一单,下班后开搞,导致没学习整理。所以第三天就简单总结下接单的代码。
=======================正文=======================
订单内容:
获取某个电商网站的所有商品信息,包括链接、价格、佣金、标题等信息。
思路:
1、分析网站,发现网站是下滑加载商品,每次10个。
2、分析接口,每次加载商品就会调用一次接口,但是传参加密了。
3、由于是简单的任务,不考虑框架和分布式等。
4、技术选型就在requests库还是selenium库。因为requests库还要考虑传参问题,selenium已经很久没用了,就决定使用selenium。
5、selenium主要针对网页源码进行操作,开始分析网页源码。发现每次刷新都会动态加载div标签。
6、每次加载商品后,不是处于网页最底部,根据此判断商品是否加载完全部。没加载完就下滑加载即可。
7、xpath定位元素,获取所需的数据,使用pandas存到excel。
思路分析完毕,开干!
1、搭建环境,用的是chrome浏览器,版本 115.0.5790.170(正式版本)。该版本好像不需要下载webdriver,我是没找到对应webdriver版本,然后启用成功啦!!!
2、导入各种包,ps:第三方库下载都很简单,就不在这写啦!
# 有一步需要用到requests.get
import requests
# 导入selenium的webdriver
from selenium import webdriver
# 本次不用显式等待,这块导入可忽略
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 用xpath查找元素位置
from selenium.webdriver.common.by import By
# 用pandas导入数据
import pandas as pd
# 用于强制等待
import time
3、封装函数
def get_resp(url,headers):
resp = requests.get(url=url,headers=headers)
return resp
def do_excel(data):
data = data
df = pd.DataFrame(data,columns=['id','链接','产品名称'])
df.to_excel('xxx.xlsx',index=False)
class browser_driver:
def __init__(self):
self.driver = webdriver.Chrome()
# 窗口最大化
self.driver.maximize_window()
# 加载网页
self.driver.get(url)
def get_page_source(self):
time.sleep(2)
html = self.driver.page_source
return html
def brower_quit(self):
self.driver.quit()
def drop_down(self):
time.sleep(2)
# 获取当前页面得高度
last_height = self.driver.execute_script('return document.body.scrollHeight')
print('当前浏览器高度{}'.format(last_height))
sum = 1
len = 1
while True:
# 下拉操作
self.driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
"""
佣金
日
月
总销量
价格
标题
点进去标题里后的佣金销售链接
"""
# 获取页面内容
html = self.get_page_source()
total = get_resp(url=api_url,headers=headers).json()['data']['page_info']['total_count']
page = get_resp(url=api_url,headers=headers).json()['data']['page_info']['total_page']
if len <= (page-1)*10:
for i in range(len,len+10):
#每次for循环后字典实例化
list_1 = []
# 标题
title = self.driver.find_element(By.XPATH,f"//div[@class='goods-list flex flex-flow-row-wrap']//*[@class='item'][{i}]//div[@class='mb5']//div[@class='goods-block']//div[@class='inner-box']//div[2]//div//div[1]//span[@class='ml4']")
# 链接
href = self.driver.find_element(By.XPATH,f"//div[@class='goods-list flex flex-flow-row-wrap']//*[@class='item'][{i}]//div//a").get_attribute('href')
# 把爬取的数据保存到字典
list_1.append(i)
list_1.append(href)
list_1.append(title.text)
# 添加到列表
list.append(list_1)
print("len:",len)
else:
val = total - (len)
print(val)
print(len+val)
for i in range(len, len + val-1):
# 每次for循环后字典实例化
list_1 = []
# 标题
title = self.driver.find_element(By.XPATH, f"//div[@class='goods-list flex flex-flow-row-wrap']//*[@class='item'][{i}]//div[@class='mb5']//div[@class='goods-block']//div[@class='inner-box']//div[2]//div//div[1]//span[@class='ml4']")
# 链接
href = self.driver.find_element(By.XPATH, f"//div[@class='goods-list flex flex-flow-row-wrap']//*[@class='item'][{i}]//div//a").get_attribute('href')
# 把爬取的数据保存到字典
list_1.append(i)
list_1.append(href)
list_1.append(title.text)
# 添加到列表
list.append(list_1)
print("len:",len)
print(list)
print('*' * 20)
len = len + 10
# 获取当前页面的高度
new_height = self.driver.execute_script('return document.body.scrollHeight')
# 判断是否到达页面底部
if last_height == new_height:
break
last_height = new_height
do_excel(list)
def test(self):
self.drop_down()
self.brower_quit()
4、执行&产出
if __name__ == '__main__':
browser_driver().test()
总结!
整体使用到的技术有selenium+requests+pandas+javascript,原本计划2个小时完成的脚本,结果花费了4个小时。一方面是selenium很久没用,需要查阅写资料。另一方面,在编写过程中也遇到些问题,花费了些时间。
问题1:要获取属性相同,但下标不一样的元素位置?所有加起来大概有487个。
方法:设置动态的xpath元素定位,需要找准下标位置,以确保找到的元素是唯一值。
问题2:一次性加载完所有商品后,页面源码太多,导致打印出来的源码不存,收集信息不全。
方法:每次加载商品后,先获取商品信息,保存到列表里。最后全部商品加载完后,再存到另一个列表,信息则会收集完整。
问题3:每次下滑会加载10个商品,到最后一轮加载,商品信息只有7个。因for循环遍历每次都是10个10个的进行,会导致找不到下标为488、489、490的元素而报错。
方法:使用if...else...,单独处理最后一轮加载的商品信息。弊端是每次更新代码要更新两处地方,懒得去优化,将就用了。。。