实例:python爬虫淘宝商品数据到 execl

本文介绍了如何使用Selenium进行网页爬虫,避开代理问题,处理动态加载的商品信息,包括获取标题、价格、销量和产地数据。特别提到通过XPath和Ajax请求来应对网页结构变化,以及如何实现页面滚动和翻页操作。
摘要由CSDN通过智能技术生成

 作为爬虫公开的网页数据的学习,又能避开代理的问题,用selenium是一个很好的方法

本文讲的是爬虫淘宝网页商品的信息:标题,价格,销量,产地(省份/城市)

有的xpath很难获取,可以选择用chorm插件xpath helper

以下主要为代码部分,有selenium基础的应该很容易看懂

部分封装

    def find_element(self, element):
        """
        这里添加了一个over_time作为查找元素的超时次数,根据系统的实际情况设置OVER_TIME的大小
        """
        for i in range(over_time):
            try:
                # return self.driver.find_element(*element)
                return self.driver.find_element(By.XPATH, element)
            except Exception as e:
                print(e)

注意:
使用selenium时,爬取商品数据时,需要下拉滚动页面到底部,这样才能获取当前页所有的商品基本展示信息。
可能原因:商品页中商品展示使用Ajax动态请求,目的是为了可以在不重载网页的条件下,与服务器进行数据交互,更新页面的局部数据。(使用Ajax请求对于流量费的节省和阻碍网络爬虫都有帮助) 

 # 滑动页面到底部
    def scroll_to_end(self):
        for i in range(3):
            self.driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
            time.sleep(2)
    
    # 点击下一页数据
    def click_page(self, page):
        try:
            return self.driver.execute_script("arguments[0].click();", page)
        except Exception as e:
            print(e)
        rand_num = random.randint(3, 6)  # 设置随机等待的时间
        time.sleep(rand_num)

goods_messege.py 

def spider_goods(num_p):
    goods_messeges = []
    title_e = "//div[@class='Title--title--jCOPvpf']"
    price_int = '//span[@class="Price--priceInt--ZlsSi_M"]'
    price_float = '//span[@class="Price--priceFloat--h2RR0RK"]'
    sale_real = '//span[@class="Price--realSales--FhTZc7U"]'
    next_page = "/html[@class='ks-webkit537 ks-webkit ks-chrome120 ks-chrome']/body/div[@id='root']/div/div[3]/div[@class='PageContent--contentWrap--mep7AEm']/div[@class='LeftLay--leftWrap--xBQipVc']/div[@class='LeftLay--leftContent--AMmPNfB']/div[@class='Pagination--pgWrap--kfPsaVv']/div[@class='next-pagination next-medium next-normal']/div[@class='next-pagination-pages']/button[@class='next-btn next-medium next-btn-normal next-pagination-item next-next']/span[@class='next-btn-helper']"
    for p in range(num_p):
        obj_tit = baseClass.BaseClass().find_elements(title_e)
        price_int_xl = baseClass.BaseClass().find_elements(price_int)
        price_float_xl = baseClass.BaseClass().find_elements(price_float)
        sale_real_xl = baseClass.BaseClass().find_elements(sale_real)
        next_page_xl = baseClass.BaseClass().find_element(next_page)
        print("第{}页数据有{}条:".format(p+1, len(obj_tit)))
        # print(len(obj_tit))
        for i in range(len(obj_tit)):
            try:
                title = obj_tit[i].text.replace(" ", "").strip()  # 空格替换为空,头尾去掉空格
                price1 = price_int_xl[i].text.replace(" ", "").strip()
                price2 = price_float_xl[i].text.replace(" ", "").strip()
                price = price1 + price2  # 整数部分加小数部分
                sale = sale_real_xl[i].text.replace(" ", "").strip()
                # 转化万为数字
                if '万' in sale:
                    sale_n = sale.split("万")[0]
                    # print(sale_n)
                    sale = int(10000 * int(sale_n))
                    # print(sale)
                else:
                    sale = int(sale.split("+")[0])
                province = baseClass.BaseClass().find_element(
                    "//div[@class='Content--contentInner--QVTcU0M']/div[{}]/a[@class='Card--doubleCardWrapper--L2XFE73']/div[@class='Card--doubleCard--wznk5U4']/div[@class='Card--mainPicAndDesc--wvcDXaK']/div[@class='Price--priceWrapper--Q0Dn7pN ']/div[1]/span[@class='Price--procity--_7Vt3mX']".format(
                        i + 1)).text.replace(
                    " ", "").strip()
                city_xl = baseClass.BaseClass().is_xpath_present(
                    "//div[@class='Content--contentInner--QVTcU0M']/div[{}]/a[@class='Card--doubleCardWrapper--L2XFE73']/div[@class='Card--doubleCard--wznk5U4']/div[@class='Card--mainPicAndDesc--wvcDXaK']/div[@class='Price--priceWrapper--Q0Dn7pN ']/div[2]/span[@class='Price--procity--_7Vt3mX']".format(
                        i + 1))
                city = city_exist(i, city_xl)
                if city == '':
                    city = province
                    goods_messeges.append([title, price, sale, province, city])
                else:
                    goods_messeges.append([title, price, sale, province, city])

            except Exception as e:
                print(e)
        if p < num_p-1:
            print("点击下一页,至第{}页".format(p + 2))
            baseClass.BaseClass().click_page(next_page_xl)
            baseClass.BaseClass().scroll_to_end()  # 滚动到底部

    mdata = pd.DataFrame(goods_messeges, columns=['标题', '价格', '销量', '省', '市'])  # 保存爬取信息
    mdata.to_csv(execl_save, index=False)  # 生成文档

测试用例:

# conding=utf-8
# @author: may
import unittest
import time
import allure
from config.globalparameter import key_messege, url
from src.common.driver_configure import GetDriver
# from src.common.logger import Logger
from src.common import baseClass
from src.pages import buttom_page
from goods import goods_messege
over_time = 3
# mylogger0 = Logger(logger='test_login').getlog()  # 存放日志


@allure.feature('selenium自动化测试: 登录')
class TestLogin(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        """
        测试前期准备条件!!!!!!!!!
        """
        cls.driver = GetDriver().get_driver()  # 实例化浏览器

        baseClass.BaseClass().start(url)
        baseClass.BaseClass().login_cookie()  # 执行完第一登录后运行
        time.sleep(3)

    @classmethod
    def tearDownClass(cls):
        """
        每个测试用例都会执行一遍setUp()和tearDown(),所以一般把tearDown()中的浏览器退出改为刷新refresh()
        如果添加了修饰器@classmethod,因为回只执行一次tearDown,所以可以直接退出浏览器quit()
        """
        try:
            pass
            # getDriver().get_driver().quit()
        except ConnectionRefusedError as e:
            print(e)
        # finally:
            # self.assertEqual([], self.verificationErrors)

    # @allure.story('登录测试')
    # @allure.severity('blocker')
    def test_0_search(self):
        self.search_page0 = buttom_page.SearchPage()
        print("进行搜索操作!!!")

        self.search_page0.input_key(key_messege)
        self.search_page0.search_b()
        time.sleep(10)

        self.search_page0.sales_rank()
        time.sleep(2)
        self.search_page0.choose_good()
        time.sleep(2)
        baseClass.BaseClass().scroll_to_end()  # 滚动到底部
        goods_messege.spider_goods(5)  # 数据爬虫. 5表示爬虫 5 页的数据

        # 存储登录的cookie
        baseClass.BaseClass().save_logincookie()
        time.sleep(10)


if __name__ == "__main__":
    unittest.main()

运行结果数据:

优化:spider_goods() 方法中,路径如果稍微变的话,很容易就定位不到,可以用page_source获取网页源,还有就是保存到mysql中python淘宝网页爬虫数据保存到 csv和mysql(selenium)

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值