zoukankan      html  css  js  c++  java
  • Selenium 抓取淘宝商品美食信息

      在使用python进行数据爬取的时候,我们发现ajax请求比较繁琐,那么有什么好的办法可以解决呢?就是使用selenium自动化工具,模拟输入点击,这样我们就可以不需要知道ajax的请求链接,从而可以直接通过类似人工的操作来模拟,从而可以获取网页数据。我们来举个例子。

      淘宝的首页,我们打开发现没有商品数据的信息,而他的数据都是通过ajax请求获取的,那么我们使用ajax请求这种方法来获取数据简单吗?我们来看看。

      我们在淘宝首页输入美食,进入美食界面我们发现他的链接:https://s.taobao.com/search?q=%E7%BE%8E%E9%A3%9F&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306    这么长,他的参数这么多,我们都需要一一来给他赋值,下面就是所有的参数的名称还有信息,而且有的参数我们根本不知道到底是什么意思。所以就很麻烦,我们就使用selenium工具来自动化输入。

      首先我们需要加载淘宝界面:

    browser = webdriver.Chrome()
    wait=WebDriverWait(browser,10)
    client=pymongo.MongoClient(MONGO_URL)
    db=client[MONGO_DB]
    browser.set_window_size(1400,900)
    
    def serach():
        try:
            browser.get('https://www.taobao.com')
            input = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#q'))
            )#通过css 选择器找到淘宝主页的输入框
            submit = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_TSearchForm > div.search-button > button'))
            )#通过css 选择器找到淘宝主页的搜索按钮
            input.send_keys('美食')#向输入框中输入美食
            submit.click()#点击搜索按钮
            total = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.total'))
            )#找到美食界面中所有的页数
            get_product()
            return total.text#返回总页数
        except TimeoutException:
            return serach()#如果没有成功则重新请求

       请求成功后,我们需要来解析网页中商品的信息:

    def get_product():
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-itemlist .items .item')))#加载找到的本页中所有的商品
        html=browser.page_source
        doc=pq(html)
        items = doc('#mainsrp-itemlist .items .item').items()#找到本页中商品的列表
        for item in items:
            product = {
                'image':item.find('.pic .img').attr('src'),#获取class为pic下的class为.img的src属性,也就是图片链接
                'price':item.find('.price').text(),#获取class为priced的文本,也就是价格
                'deal':item.find('.deal-cnt').text()[:-3],#获取class为deal-cnt的文本的倒数第三个之前的文本,也就是成交量(多少人付款)
                'title':item.find('.title').text(),#获取商品的名称
                'shop':item.find('.shop').text(),#获取商品的店铺名称
                'location':item.find('.location').text()#获取商品的产地
            }
            save_mongodb(product)

      现在我们只获取了一页的内容,我们需要获取全部的内容,有两种办法:

      第一种:selenium自动点击下一页,但是该方法的缺点就是,如果改页没有加载成功,我们就爬取不到改页的内容,无法判断是否爬取了这页

      第二种:循环,自动输入需要跳转的下一页的页码,通过判断输入的内容和当前页码是否一致判断是否成功加载了本页,我们采用第二种方法。

    def next_page(current_page):
        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(current_page)#在输入框中输入请求的页码
            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(current_page)))
            # 判断请求的页码是否等于当前页,如果等于说明加载成功
            get_product()
        except TimeoutException:
            return next_page(current_page)# 如果失败则重新加载本页

    然后我们还可以将数据保存在mongdb中,下面是全部代码:

    import re
    
    import pymongo
    from selenium import webdriver
    from selenium.common.exceptions import TimeoutException
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from pyquery import PyQuery as pq
    from config import *
    
    browser = webdriver.Chrome()
    wait=WebDriverWait(browser,10)
    client=pymongo.MongoClient(MONGO_URL)
    db=client[MONGO_DB]
    browser.set_window_size(1400,900)
    
    def serach():
        try:
            browser.get('https://www.taobao.com')
            input = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR,'#q'))
            )#通过css 选择器找到淘宝主页的输入框
            submit = wait.until(
                EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_TSearchForm > div.search-button > button'))
            )#通过css 选择器找到淘宝主页的搜索按钮
            input.send_keys('美食')#向输入框中输入美食
            submit.click()#点击搜索按钮
            total = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.total'))
            )#找到美食界面中所有的页数
            get_product()
            return total.text#返回总页数
        except TimeoutException:
            return serach()#如果没有成功则重新请求
    
    def next_page(current_page):
        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(current_page)
            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(current_page)))
            get_product()
        except TimeoutException:
            return next_page(current_page)
    def get_product():
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-itemlist .items .item')))#加载找到的本页中所有的商品
        html=browser.page_source
        doc=pq(html)
        items = doc('#mainsrp-itemlist .items .item').items()#找到本页中商品的列表
        for item in items:
            product = {
                'image':item.find('.pic .img').attr('src'),#获取class为pic下的class为.img的src属性,也就是图片链接
                'price':item.find('.price').text(),#获取class为priced的文本,也就是价格
                'deal':item.find('.deal-cnt').text()[:-3],#获取class为deal-cnt的文本的倒数第三个之前的文本,也就是成交量(多少人付款)
                'title':item.find('.title').text(),#获取商品的名称
                'shop':item.find('.shop').text(),#获取商品的店铺名称
                'location':item.find('.location').text()#获取商品的产地
            }
            save_mongodb(product)
    
    def save_mongodb(result):
        try:
            if db[MONGO_TABLE].insert(result):
                print('保存到MongoDb成功!',result)
        except Exception:
            print('存储失败!')
    
    def main():
        try:
            total=serach()
            total=int(re.compile('(d+)').search(total).group(1))
            for i in range(2,10):
                next_page(i)
        except Exception:
            print('出错了')
        finally:
            browser.close()
    
    if __name__ == '__main__':
        main()

    新建config.py文件:

    MONGO_URL='localhost'
    MONGO_DB='taobao'
    MONGO_TABLE='meishi'

    下面就是在MongoDB中的商品信息了。

  • 相关阅读:
    经典排序算法动态图
    oracle之触发器
    假如有Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小
    spring mvc将对象转换为json返回的配置
    用jackson包实现json、对象、Map之间的转换
    不加好友实现QQ在线代码状态临时会话
    QQ自动强制加好友代码html
    maven 私服搭建
    java定时任务
    ORACLE数据库表解锁record is locked by another user
  • 原文地址:https://www.cnblogs.com/zll20153246/p/9676104.html
Copyright © 2011-2022 走看看