使用selenium爬取淘宝

Posted 山水无期

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用selenium爬取淘宝相关的知识,希望对你有一定的参考价值。

使用selenium爬取淘宝

一、出现的问题

    前段时间在使用selenium对淘宝进行模拟登陆的时候,输入完正好和密码,然后验证码无论如何都不能划过去。找了好久,原来是因为selenium在浏览器中运               行的时候会暴露一些特征变量,被识别出来是爬虫,所以无法进行登录操作。如在非selenium运行的时候"window.navigator.webdriver"是undefined,但是在                   selenium运行的情况下,它是true。

二、解决方法

     1、网上大部分的方案

    启动浏览器的时候加上一些配置和手动把webdriver的属性设置为undefined。

  option = ChromeOptions()
    option.add_experimental_option(\'excludeSwitches\', [\'enable-automation\'])
    #option.add_argument(\'--headless\')
    web= webdriver.Chrome(options=option)
    web.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
       "source": """Object.defineProperty(navigator, \'webdriver\', {get: () => undefined})""",
    })

    但是这个方案并不能有效的解决,于是又在网上找到另外的一种方案。

    2、使用python的mitmproxy库进行操作。

    mitmproxy 就是用于 MITM 的 proxy,MITM 即中间人攻击(Man-in-the-middle attack)。用于中间人攻击的代理首先会向正常的代理一样转发请求,保障服务端与客户端的通信,其次,会适时的查、        记录其截获的数据,或篡改数据,引发服务端或客户端特定的行为。

    使用 pip install mitmproxy 

    新建一个py文件,命名随意,这里命名为modify_response.py

    

# coding: utf-8
# modify_response.py

from mitmproxy import ctx


def response(flow):
    """修改响应数据
    """
    if \'/js/yoda.\' in flow.request.url:
        # 屏蔽selenium检测
        for webdriver_key in [\'webdriver\', \'__driver_evaluate\', \'__webdriver_evaluate\', \'__selenium_evaluate\',
                              \'__fxdriver_evaluate\', \'__driver_unwrapped\', \'__webdriver_unwrapped\',
                              \'__selenium_unwrapped\', \'__fxdriver_unwrapped\', \'_Selenium_IDE_Recorder\', \'_selenium\',
                              \'calledSelenium\', \'_WEBDRIVER_ELEM_CACHE\', \'ChromeDriverw\', \'driver-evaluate\',
                              \'webdriver-evaluate\', \'selenium-evaluate\', \'webdriverCommand\',
                              \'webdriver-evaluate-response\', \'__webdriverFunc\', \'__webdriver_script_fn\',
                              \'__$webdriverAsyncExecutor\', \'__lastWatirAlert\', \'__lastWatirConfirm\',
                              \'__lastWatirPrompt\', \'$chrome_asyncScriptInfo\', \'$cdc_asdjflasutopfhvcZLmcfl_\']:
            ctx.log.info(\'Remove "{}" from {}.\'.format(webdriver_key, flow.request.url))
            flow.response.text = flow.response.text.replace(\'"{}"\'.format(webdriver_key), \'"NO-SUCH-ATTR"\')
            print(webdriver_key)
        flow.response.text = flow.response.text.replace(\'t.webdriver\', \'false\')
        flow.response.text = flow.response.text.replace(\'ChromeDriver\', \'\')

      然后在cmd中使用命令运行脚本:mitmdump.exe -p 端口号 -s modify_response.py

      然后再执行selenium的脚本即可实现正常的通过selenium进行登录淘宝网站,之前设置的ChromeOptions也要加上。当然要设置代理。

三、代码实现

      此次代码实现了自动登录,输入关键词,爬取淘宝商品的商品名称,店铺的省份,商品的价格和人气等信息,并将这些信息保存在CSV文件中,以方便进行数据的分析。具体代码如下:

from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import csv




def main():
    #登录设置
    #会开会话
    option = ChromeOptions()
    option.add_experimental_option(\'excludeSwitches\', [\'enable-automation\'])
    #option.add_argument(\'--headless\')
    web= webdriver.Chrome(options=option)
    web.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
       "source": """Object.defineProperty(navigator, \'webdriver\', {get: () => undefined})""",
    })
    web.get(\'https://login.taobao.com/member/login.jhtml\')


    #输入账号和密码
    web.find_element_by_xpath(\'//*[@id="fm-login-id"]\').send_keys(\'xxxxxx\')
    web.find_element_by_xpath(\'//*[@id="fm-login-password"]\').send_keys(\'xxxxxxxx\')
    web.find_element_by_xpath(\'//*[@id="login-form"]/div[4]/button\').click()
    #进入首页
    try:
        WebDriverWait(web,20).until(EC.element_to_be_clickable((By.XPATH,\'//*[@id="J_SiteNavHome"]/div/a/span\'))).click()
    except:
        pass


    # 搜索商品
    goods=input(\'请输入您要搜索的商品:\')
    WebDriverWait(web,20).until(EC.presence_of_element_located((By.XPATH,\'//*[@id="q"]\'))).send_keys(goods)
    WebDriverWait(web,20).until(EC.element_to_be_clickable((By.XPATH,\'//*[@id="J_TSearchForm"]/div[1]/button\'))).click()

    try:
        #查找共计页数
        sum_page=web.find_element_by_xpath(\'//*[@id="mainsrp-pager"]/div/div/div/div[1]\').text
    except:
        # 防止出现滑块的验证
        WebDriverWait(web,5).until(EC.presence_of_element_located((By.XPATH,\'//*[@id="nc_1_n1z"]\')))
        actoin = ActionChains(web)
        drag = web.find_element_by_xpath(\'//*[@id="nc_1_n1z"]\')
        actoin.drag_and_drop_by_offset(drag,300,0).perform()
        WebDriverWait(web,20).until(EC.presence_of_element_located((By.XPATH,\'//*[@id="mainsrp-pager"]/div/div/div/div[1]\')))
        sum_page = web.find_element_by_xpath(\'//*[@id="mainsrp-pager"]/div/div/div/div[1]\').text

    print(goods,sum_page)
    #输入查找范围
    min_page = int(input(\'请输入搜索的最小页数:\'))
    max_page = int(input(\'请输入搜搜的最大页数:\'))

    #解析和保存数据
    f = open(\'C:/Users/sunshine/Desktop/课件/图片/爬取的数据/\' + \'淘宝\' + goods+\'.csv\', \'w+\', encoding=\'utf-8\',newline=\'\')
    csvwrite=csv.writer(f)
    csvwrite.writerow((\'shop_name\', \'goods_name\', \'loc\', \'prices\', \'sum_body\'))

    for min_page in range(min_page,max_page+1):
        try:
            if min_page!=1:
                key_=WebDriverWait(web, 20).until(
                EC.element_to_be_clickable((By.XPATH, \'//*[@id="mainsrp-pager"]/div/div/div/div[2]/input\')))
                key_.clear()
                key_.send_keys(min_page)
                key_.send_keys(Keys.ENTER)
                #WebDriverWait(web,20).until(EC.element_to_be_clickable((
                    #By.XPATH,\'//*[@id="mainsrp-pager"]/div/div/div/div[2]/span[3]\'))).click()
                #web.find_element_by_xpath(\'//*[@id="mainsrp-pager"]/div/div/div/div[2]/span[3]\').click()
                #web.execute_script("window.scrollTo(0,document.body.scrollHeight);")
                time.sleep(2)
                #WebDriverWait(web, 20).until(
                    #EC.element_to_be_clickable((By.XPATH, \'//*[@id="mainsrp-pager"]/div/div/div/div[2]/span[3]\')))
            else:
                web.execute_script("window.scrollTo(0,document.body.scrollHeight);")
                time.sleep(2)

        except Exception as e:
            xpath_=web.find_element_by_xpath(\'//*[@id="J_sufei"]/iframe\')
            web.switch_to.frame(xpath_)
            action=ActionChains
            drag=web.find_element_by_xpath(\'//*[@id="nc_1__scale_text"]/span\')
            action(web).drag_and_drop_by_offset(drag,300,0).perform()
            web.switch_to.frame(web.find_element_by_xpath(\'//*[@id="CrossStorageClient-ba26ffda-7fa9-44ef-a87f-63c058cd9d01"]\'))
            print(e,\'出现滑块验证\')
            key_ = WebDriverWait(web, 20).until(
                EC.element_to_be_clickable((By.XPATH, \'//*[@id="mainsrp-pager"]/div/div/div/div[2]/input\')))
            key_.clear()
            key_.send_keys(min_page)
            key_.send_keys(Keys.ENTER)
            #WebDriverWait(web, 20).until(
                #EC.element_to_be_clickable((By.XPATH, \'//*[@id="mainsrp-pager"]/div/div/div/div[2]/span[3]\'))).click()
            time.sleep(2)


        list = web.find_elements_by_xpath(\'//*[@id="mainsrp-itemlist"]/div/div/div[1]/div\')
        for items in list:
            prices = items.find_element_by_xpath(\'./div[2]/div[1]/div[1]/strong\').text
            prices = float(prices)
            goods_name=items.find_element_by_xpath(\'./div[2]/div[2]/a\').text
            body=items.find_element_by_xpath(\'./div[2]/div[1]/div[2]\').text
            if \'\' in body:
                body=re.findall(r\'\\d+.\\d+|\\d+\', body)[0]
                sum_body=float(body)*10000
            elif len(body)!=0:
                body = re.findall(r\'\\d+.\\d+|\\d+\', body)[0]
                sum_body = float(body)
            else:
                sum_body=None



            shop_name=items.find_element_by_xpath(\'./div[2]/div[3]/div[1]/a/span[2]\').text
            loc=items.find_element_by_xpath(\'./div[2]/div[3]/div[2]\').text[:3]
            #tuple=((shop_name,goods_name,loc,prices,sum_body))
            print((shop_name,goods_name,loc,prices,sum_body))
            csvwrite.writerow((shop_name,goods_name,loc,prices,sum_body))
        print(\'===============第\'+str(min_page)+\'页已爬取完成!=======================\')
    f.close()
    web.close()
    return goods

 

 

 

以上是关于使用selenium爬取淘宝的主要内容,如果未能解决你的问题,请参考以下文章

使用Selenium爬取淘宝商品

selenium跳过webdriver检测并爬取淘宝我已购买的宝贝数据

爬虫实例之selenium爬取淘宝美食

用selenium爬取淘宝美食

利用Selenium爬取淘宝商品信息

用selenium爬取淘宝美食