• 爬虫实战01_淘宝模拟登录


    需求:通过淘宝模拟登录打造一个关键词搜索库

    '''
    思路:
        1. 打开浏览器,输入关键词搜索
        2. 跳转至登录页面,使用微博登录
        3. 登录完成获取列表页
        4. 解析数据
        5. 保存数据
    '''
    import time
    import re
    import pymongo
    from pyquery import PyQuery as pq
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.chrome.options import Options
    # 这个包是导入配置包,里面可以存放数据库连接和关键词以及登录账号密码等常量
    from settings import *
    
    
    # 将浏览器设置为无头浏览器
    chrome_options = Options()
    chrome_options.add_argument("headless")
    chrome_options.add_argument("--disable-gpu")
    # 打开浏览器
    chrome = webdriver.Chrome()
    # 为了保证不出错,定义一个显式等待变量
    wait = WebDriverWait(chrome, 10)
    # 连接MongoDB
    client = pymongo.MongoClient(MONGO_URL)
    db = client[MONGO_DB]
    
    def search():
        '''
        此函数主要用来模拟登录以及获取第一页数据
        '''
        try:
            chrome.get('https://www.taobao.com/')
            # 输入关键字点击搜索
            input = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, "#q")))
            submit = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, "#J_TSearchForm > div.search-button > button")))
            input.send_keys(KEY_WORD)
            time.sleep(1)
            submit.click()
            # 模拟登录(用微博登录)
            login = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, "#login-form > div.login-blocks.sns-login-links > a.weibo-login"))).click()
            chrome.find_element_by_xpath("//*[@id='pl_login_logged']/div/div[2]/div/input").send_keys(USERNAME)
            time.sleep(1)
            chrome.find_element_by_xpath("//*[@id='pl_login_logged']/div/div[3]/div/input").send_keys(PASSWORD)
            time.sleep(1)
            chrome.find_element_by_xpath("//*[@id='pl_login_logged']/div/div[7]/div[1]/a/span").click()
            # 获取总页数
            total_page = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.total")))
            # 解析数据 注意:等待可以获取到底部总页数的时候,说明列表页已经加载完毕,可以开始解析数据
            get_product()
            return total_page.text
        except TimeoutError:
            # 如果请求出错,递归调用自身,相当于retrying
            return search()
    
    def next_page(page_num):
        '''
        这个函数用来请求列表页
        '''
        try:
            # 请求下一页
            input = wait.until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input")))
            submit = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit"))
            )
            input.clear()
            input.send_keys(page_num)
            submit.click()
            wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > ul > li.item.active > span"),str(page_num)))
            # 解析数据
            get_product()
        except TimeoutError:
            next_page(page_num)
    
    def get_product():
        '''
        这个函数用来解析数据,解析库可以根据自己喜好更改
        '''
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-itemlist .items .item')))
        html = chrome.page_source
        doc = pq(html)
        items = doc('#mainsrp-itemlist .items .item').items()
        for item in items:
            product = {
                'image': item.find('.pic .img').attr('src'),
                'price': item.find('.price').text(),
                'deal': item.find('.deal-cnt').text()[:-3],
                'title': item.find('.title').text().strip(),
                'shop': item.find('.shop').text(),
                'location': item.find('.location').text()
            }
            print(product)
            save_to_mongo(product)
    
    def save_to_mongo(result):
        '''
        保存到MongoDB
        '''
        try:
            if db[MONGO_TABLE].insert_one(result):
                print('保存到MONGODB成功', result)
        except Exception:
            print('保存到MONGODB失败', result)
    
    def main():
        '''
        主要爬网逻辑
        '''
        try:
            total = search()
            # 获取总页数
            total = int(re.compile('(d+)').search(total).group(1))
            for i in range(2, total+1):
                next_page(i)
        except Exception:
            print('出错了')
        finally:
            chrome.close()
    
    if __name__ == '__main__':
        main()
    

    爬取结果

    以上代码不足之处,没有使用代理,淘宝网算是反爬比较厉害的网站,时不时会跳出来浏览限制(比如让输入验证码),一般都是因为同一个ip短时间内数据获取量太快
    提供三个解决方案
    1. 外接打码平台,识别验证码,返回输入
    2. 如果比较牛逼,可以使用深度学习图像识别识别验证码输入
    3. 使用代理,这个是个人觉得比较好的解决方案,从可行性和解决问题的本质上算比较优的解决方案

    配置文件内容

    微博账号和密码(微博要和淘宝是同一个手机号哦)
    USERNAME = '----------'
    PASSWORD = '----------'
    MongoDB配置
    MONGO_URL = 'localhost'
    MONGO_DB = 'taobao'
    MONGO_TABLE = 'product'
    关键词
    KEY_WORD = '美食'

  • 相关阅读:
    1120. Maximum Average Subtree 子树平均值的最大值
    490. The Maze 迷宫踢足球
    323. Number of Connected Components in an Undirected Graph 连通图的数量
    done infosys_不告你答案的面试
    MyBatis(三)全局配置文件 之 typeHandlers 类型处理器
    MyBatis(三)全局配置文件 之 typeAliases 类型命名
    MyBatis(三)全局配置文件 之 properties 属性
    MyBatis(三)全局配置文件 之 settings 设置
    MyBatis(三)全局配置文件
    MyBatis(二)HelloWorld 案例
  • 原文地址:https://www.cnblogs.com/wsilj/p/12735063.html
Copyright © 2020-2023  润新知