Python爬虫实战——Lazada商品数据(selenium自动化爬虫,xpath定位)

前言

        在此说明,这个项目是我第一次真正去爬的一个网站,里面写的代码我自己都看不下去,但是已经不想花时间去重构了,所以看个乐呵就好,要喷也可以(下手轻一点)。这篇文算是记录我的学习中出现的一些问题,不建议拿来学习和真拿我的代码去爬Lazada的数据,当然看看我的思路还是可以的。

目标

        我的目标是拿到个分类下的商品数据

Python爬虫实战——Lazada商品数据(selenium自动化爬虫,xpath定位)_第1张图片

 Python爬虫实战——Lazada商品数据(selenium自动化爬虫,xpath定位)_第2张图片

 爬虫思路

        1.获取各个分类的链接

        2.获取各个分类下的商品链接

        3.通过商品链接获取到需要的商品数据

需要用到的包和工具准备

import time
import openpyxl
import requests
import re
from lxml import etree
from selenium.webdriver.common.by import By
import bag  # 这个包是别人写好给我的,我会在下面把用到的方法放出来

         这个bag包里面的很多参数是不起作用的,可以不用管它。这里给Chrome浏览器设置了一个9222端口方便用程序控制自己打开的浏览器

 class Bag:   
    def web_debug():
        chrome_options = Options()
        chrome_options.add_experimental_option('debuggerAddress', '127.0.0.1:9222')
        chrome_options.page_load_strategy = 'eager'
        chrome_options.add_argument('–disable-gpu')  # 谷歌文档提到需要加上这个属性来规避bug
        chrome_options.add_argument('--incognito')
        chrome_options.add_argument('--disable-javascript')
        chrome_options.add_argument('--enable-automation')
        chrome_options.add_argument('--no-sandbox')  # 解决DevToolsActivePort文件不存在的报错
        chrome_options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片, 提升速度
        web = Chrome(service=Service(), options=chrome_options)
        return web

右键Chrome浏览器的属性把目前路径改成如下:

C:\Program Files\Google\Chrome\Application\chrome.exe (括号里面的是解释用的时候记得删掉:前面是你谷歌浏览器的放在文件夹里的位置)[--headless] --remote-debugging-port=9222 --user-data-dir="D:\工作文件\data  (还要创建一个放数据的文件夹)

设置好后就可以win+R打开运行窗口,输入cmd打开Windows命令行窗口:

输入如下命令:

cd C:\Program Files\Google\Chrome\Application\ (浏览器在电脑中的位置)
chrome.exe --remote-debugging-port=9222 --user-data-dir="D:\工作文件\data"

就可以打开一个浏览器,到时候我们让程序通过端口控制自己打开的浏览器,这样好突破网站的反爬手段

商品链接爬取

讲了那么多终于开始准备爬虫了(再次吐槽自己写的是什么鬼东西搞这么复杂),下面是进行第一步拿到分类的链接。

通过下一页还有F12的一个观察,发现链接数据都是通过访问如下链接请求回来的

Python爬虫实战——Lazada商品数据(selenium自动化爬虫,xpath定位)_第3张图片

 这是第一个分类第三页的链接:https://www.lazada.sg/shop-power-banks/?ajax=true&isFirstRequest=true&page=3&spm=a2o42.searchlistcategory.cate_1_1.2.46115305qPLfPu

 然后?之后的链接都是可以不用要的,但是为了页数我们只把page= 后面的链接删了,page是控制页数的参数

整理如下

https://www.lazada.sg/shop-power-banks/?ajax=true&isFirstRequest=true&page=3

 再观察发现链接中的这部分

 刚好就是最小的那个分类的名字,那这个链接就好搞了

通过xpath定位可以找到分类的链接

 爬取分类链接的代码如下:

头文件和cookie,要设置好,不然网站不会返回数据

headers = {
    'User-Agent': ''
}
cookies = {
    'cookie': ''
}
def shop_spider(url):
    '''
    遇到的问题:
        1.在获取商品分类界面的url时request访问回来的数据不全(网页源代码有数据)。 解决方法:这个网站需要添加cookie
        2.形成的JSON链接有一些是错误的,使用时需要抛出异常
        3.只爬取了分类下的第一页的链接
    '''
    # 获取商品分类界面url
    req = requests.session().get(url, headers=headers, cookies=cookies).text
    ht = etree.HTML(req)
    li = ht.xpath("//li[@class='lzd-site-menu-grand-item']/a/@href")  # 分类界面
    # 组合获取到的分类名字,形成分类链接
    url_list = []
    for i in li:
        url_list.append('https:' + i + '?ajax=true&isFirstRequest=true&page=1')
    # 将获取到的链接存入到txt文档中
    f = open('D:\\工作文件\\lazadaurl.txt', 'w', encoding='utf8')
    f.write('\n'.join(url_list))
    f.close()
shop_spider('https://www.lazada.sg/')  # 启动函数

很好,现在我们完成了第一步,现在到第二步:从获取到的分类界面链接里面提取出商品的链接

实现代码:

def lazada_json():
    f = open('D:/工作文件/lazadaurl.txt') # 这里放的是前面爬到的分类链接
    ls = []
    for i in f:
        try:
            # 发起request请求session是保存之前cookie等数据,拿JSON格式的数据回来
            req = requests.session().get(i, headers=headers, cookies=cookies).json()
            # 正则匹配出需要的url
            js = re.findall(ir, str(req))
            # 集合(set)去重
            li = list(set(js))
            # 循环寻找可以访问的链接(找回来的数据是只有//www开头的链接才可以访问),是就写进一个新的列表,不是就pass
            for j in li:
                if j[:5] == "//www":
                    ls.append(j)
                else:
                    pass
        except Exception as arr:
            print(arr)  # 抛出异常名字和出现异常的链接
            continue  # 抛出异常继续爬取
    # 保存爬取到的链接,以待后面爬商品的详情数据
    url = []
    for i in ls:
        url.append('https:' + i)  # 组合成商品详情页链接
    f = open('D:\\工作文件\\url.txt', 'w')
    f.write(str('\n'.join(url)))
    f.close()

商品数据爬取

接下来到我们的第三步,爬商品详情页的数据了。这也是本人最不满意的一部分,也是问题最多的一部分。

拿数据的部分如下图,当然还有商品的链接:

Python爬虫实战——Lazada商品数据(selenium自动化爬虫,xpath定位)_第4张图片

 Python爬虫实战——Lazada商品数据(selenium自动化爬虫,xpath定位)_第5张图片

 

爬取代码如下:

def lazada_data():
    f = open('D:/工作文件/没爬的url1.txt', encoding='utf8')
    p = open(r'D:\工作文件\没爬的url.txt', 'a')
    url = []
    for r in f:
        url.append(r)
    l = openpyxl.load_workbook('D:/工作文件/text.xlsx')  # 读取已经有的工作簿
    sheet1 = l['sheet1']  # 创建sheet工
    ch = bag.Bag.web_debug()  # 使用bag包里面的方法创建浏览器
    x = 1  # 这是写入到Excel里面的第几行,也表示着现在爬到了第几条链接
    for i in url[0:]:  # 这里可以选择从第几条开始爬,记得要-1,因为列表是从0开始数
        data = []
        bq1 = []
        ch.get(i)
        # 出现验证码拦截界面时停止程序,手动处理验证码之后再从新启动
        if ch.title == '验证码拦截':
            print('在第' + str(x) + '终止')
            l.save('D:/工作文件/text.xlsx')  # 保存.xls到当前工作目录
            exit(0)
        # 处理当商品已经下架之后的状况
        if ch.title == 'non-existent products':
            continue
        try:
            ch.implicitly_wait(100)
            time.sleep(1)
            data.append(ch.find_element(By.XPATH, '//*[@id="module_product_title_1"]/div/div/h1').text)  # 标题
            data.append(ch.find_element(By.XPATH, '//*[@id="module_product_brand_1"]/div/a[1]').text)  # 品牌
            bq = ch.find_elements(By.XPATH, '//*[@id="J_breadcrumb"]/li/span/a')  # 分类标签
            for k in bq:
                bq1.append(k.get_attribute('text'))
            data.append(bq1)
            data.append(ch.find_element(By.XPATH, '//*[@id="module_product_review_star_1"]/div/a').text)  # 评级
            req = requests.session().get(i, headers=headerss, cookies=cookiess).text
            et = etree.HTML(req)
            jj = re.findall(jre, str(req))
            # 判断有没有拿到简介的数据,没有就跳过,加入到后续补爬的文件里面
            if jj:
                data.append(jj)  # 简介
            else:
                print('第' + str(x) + '条链接的简介没拿到!')
                p.write(i)
                continue
            data.append(et.xpath("//img[@class='pdp-mod-common-image item-gallery__thumbnail-image']/@src"))  # 商品图片链接

            data.append(i)  # 商品详情页链接
            # 保存到xlsx文件里,因为这里列表里面套列表([1,2,[4,5,6],3]),所以加个判断(当然这部分还可以优化,懒了,不想改了)
            for y in range(len(data)):
                if type(data[y]) != list:
                    sheet1.cell(x, y + 1).value = data[y]  # 写入数据参数对应 行, 列, 值
                else:
                    sheet1.cell(x, y + 1).value = '\n'.join(data[y])
            x += 1
        except Exception as arr:
            print('第' + str(x) + '条错误,已经加入未爬取文件')
            p.write(i)
            continue
        if x % 500 == 0:
            l.save(r'D:/工作文件/text.xlsx')  # 保存.xls到当前工作目录
    l.save('D:/工作文件/text.xlsx')  # 保存.xls到当前工作目录
    p.close()

 main函数启动,一个个起就可以了

if __name__ == '__main__':
    # shop_spider('https://www.lazada.sg/')
    # lazada_json()
    lazada_data()

商品详情的数据爬取这部分在分类标签这部分用了拦截器函数,具体的原理我还没研究明白

总结

        小小的总结一下吧,在获取链接的那两部分我个人感觉还OK,就是在数据获取那边用的方法非常的混乱,用了selenium自动化爬虫,接下又对同一个链接发request请求,说实话真的有点多余了,但是我有不知道怎么把拿商品的介绍这部分,所以才使用了这样的一个非常臃肿的方法(不要学)。

        具体的结果图我就不放出来了,本来就是记录一下自己的学习过程的。

你可能感兴趣的:(python,windows,pycharm,网络爬虫)