美文网首页Python3网络爬虫开发实战我爱编程
(九)使用Selenium+Chrome/PhantomJS(模

(九)使用Selenium+Chrome/PhantomJS(模

作者: 努力奋斗的durian | 来源:发表于2018-02-11 14:02 被阅读108次

    最近更新:2018-02-11

    1.相关工具介绍
    2.目标站点分析
    3.流程框架及准备工作
    4.爬虫步骤
    学习参考链接:
    Python3网络爬虫开发实战 7.1-Selenium的使用
    Python3网络爬虫开发实战 7.4-使用Selenium爬取淘宝商品

    1.相关工具介绍

    • Selenium是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScript动态渲染的页面来说,此种抓取方式非常有效。
    • PhanttomJS是无界面浏览器,因为老是开着浏览器,不方便.
    • Chrome是个浏览器

    2.目标站点分析

    本节中,我们要利用Selenium抓取淘宝商品并用pyquery解析得到商品的图片、名称、价格、购买人数、店铺名称和店铺所在地信息,并将其保存到MongoDB。

    • 打开淘宝网:https://www.taobao.com/
    • 搜索一个关键词:美食,看到非常好多吃的,我们现在就是要爬取这些内容.
    • 打开淘宝页面,搜索商品,比如美食,此时打开开发者工具,截获Ajax请求,我们可以发现获取商品列表的接口,如图7-19所示。但是这个Ajax接口包含几个参数,参数不能直接发现其规律,如果要去探寻它的生成规律,也不是做不到,但这样相对会比较烦琐,所以如果直接用Selenium来模拟浏览器的话,就不需要再关注这些接口参数了,只要在浏览器里面可以看到的,都可以爬取。这也是我们选用Selenium爬取淘宝的原因


    • 爬取的顺序是:需要模拟在输入框输入关键词,点击搜索按钮,获取首页的内容,模拟点击翻页,获得每页源代码,并分析商品信息,存储到MongoDB数据库.

    3.流程框架及准备工作

    3.1流程框架

    3.2准备工作

    本节中,我们首先以Chrome为例来讲解Selenium的用法。在开始之前,请确保已经正确安装好Chrome浏览器并配置好了ChromeDriver;另外,还需要正确安装Python的Selenium库;最后,还对接了PhantomJS和Firefox,请确保安装好PhantomJS和Firefox并配置好了GeckoDriver。如果环境没有配置好,可参考如下崔庆才的博客链接。
    Python3网络爬虫开发实战4.3-使用pyquery
    Python3网络爬虫开发实战1.5.2-PyMongo的安装
    Python3网络爬虫开发实战1.4.2-MongoDB安装
    Python3网络爬虫开发实战1.3.3-pyquery的安装
    Python3网络爬虫开发实战1.2.5-PhantomJS的安装
    Python3网络爬虫开发实战1.2.3-ChromeDriver的安装
    Python3网络爬虫开发实战 1.2.2-Selenium的安装

    4.爬虫步骤

    4.1声明浏览器对象

    4.1.1本次案例声明浏览器方法
    from selenium import webdriver
    browser = webdriver.Chrome()
    

    Chrome浏览器会自动打开,如下截图,则说明驱动Chrome浏览器成功:


    4.1.2声明浏览器拓展学习内容

    Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS。

    此外,我们可以用如下方式初始化:

    
    browser = webdriver.Chrome()
    browser = webdriver.Firefox()
    browser = webdriver.Edge()
    browser = webdriver.PhantomJS()
    browser = webdriver.Safari()
    

    这样就完成了浏览器对象的初始化并将其赋值为browser对象。接下来,我们要做的就是调用browser对象,让其执行各个动作以模拟浏览器操作。

    4.2定义搜索的方法

    4.2.1定义搜索的方法-search()
    • 这里首先构造了一个WebDriver对象,使用的浏览器是Chrome,然后指定一个关键词,如美食.
    • 等待加载时,我们使用了WebDriverWait对象,它可以指定等待条件,同时指定一个最长等待时间,这里指定为最长10秒。如果在这个时间内成功匹配了等待条件,也就是说页面元素成功加载出来了,就立即返回相应结果并继续向下执行,否则到了最大等待时间还没有加载出来时,就直接抛出超时异常。
    • 比如,我们最终要等待商品信息加载出来,就指定了presence_of_element_located这个条件,然后传入了#q这个选择器,而这个选择器对应的内容就是搜索商品的输入框.
    • 关于搜索美食操作,这里首先获取商品输入框,赋值为input,然后获取“确定”按钮,赋值为submit.
    • 调用send_keys()方法将美食填充到输入框中,然后点击“确定”按钮(submit.click())即可。
    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
    
    browser = webdriver.Chrome()
    wait = WebDriverWait(browser, 10)
    
    def search():
        browser.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("美食") #操作动作
        submit.click()
        
    def main():
        search()
        
        
    if __name__=='__main__':
        main()
    
    4.2.2selenium的拓展学习内容
    • 官方学习资料:Selenium with Python
    • Python3网络爬虫开发实战7.1-Selenium的使用
    • 显式等待
      这里还有一种更合适的显式等待方法,它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。示例如下:
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
     
    browser = webdriver.Chrome()
    browser.get('https://www.taobao.com/')
    wait = WebDriverWait(browser, 10)
    input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
    button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
    print(input, button)
    

    这里首先引入WebDriverWait这个对象,指定最长等待时间,然后调用它的until()方法,传入要等待条件expected_conditions。比如,这里传入了presence_of_element_located这个条件,代表节点出现的意思,其参数是节点的定位元组,也就是ID为q的节点搜索框。

    这样可以做到的效果就是,在10秒内如果ID为q的节点(即搜索框)成功加载出来,就返回该节点;如果超过10秒还没有加载出来,就抛出异常。

    对于按钮,可以更改一下等待条件,比如改为element_to_be_clickable,也就是可点击,所以查找按钮时查找CSS选择器为.btn-search的按钮,如果10秒内它是可点击的,也就是成功加载出来了,就返回这个按钮节点;如果超过10秒还不可点击,也就是没有加载出来,就抛出异常。

    运行代码,在网速较佳的情况下是可以成功加载出来的。

    4.3获取总页面的页数内容-research()

    4.3.1本次案例模拟翻页的方法
    • 首先获取页数有多少页,点击美食搜索之后,下一步肯定是要等待页数加载出来,需要再加一个等待的判断,即
    • 那么,怎样知道有没有跳转到对应的页码呢?我们可以注意到,成功跳转某一页后,页码都会高亮显示,如图7-25所示。total=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.total")))



      这里商品的搜索结果一般最大都为100页,要获取每一页的内容,只需要将页码从1到100顺序遍历即可,页码数是确定的。所以,直接在页面跳转文本框中输入要跳转的页码,然后点击“确定”按钮即可跳转到页码对应的页面。

    • 使用wait时间过久会出现异常.因此增加try and except:
    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
    
    
    
    browser = webdriver.Chrome()
    wait = WebDriverWait(browser, 10)
    
    def search():
        try:
            browser.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("美食") #操作动作
            submit.click()
            total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.total")))
            return total.text#返回内容
        except TimeoutException:
            return search()                                         
                                                   
    def main():
        total=search()
        print(total)
        
    if __name__=='__main__':
        main()
    

    最终显示的结果:


    • 需要用正则表达式提取100
      total=search()
      total=int(re.compile('(\d+)').search(total).group(1))#打印出来可能是个字符串,所以要转义为整数
    import re
    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
    
    
    
    browser = webdriver.Chrome()
    wait = WebDriverWait(browser, 10)
    
    def search():
        try:
            browser.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("美食") #操作动作
            submit.click()
            total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.total")))
            return total.text#返回内容
        except TimeoutException:
            return search()                                         
                                                   
    def main():
        total=search()
        total=int(re.compile('(\d+)').search(total).group(1))
        print(total)
        
    if __name__=='__main__':
        main()
    

    最终显示的结果:


    4.3.2获得总页面页数的学习内容
    • 获取SELECTOR的目标值方法


    4.4循环-遍历每页-next_page(page_number)

    -刚才我们所定义的next_page(page_number)方法需要接收参数page,page代表页码。这里我们实现页码遍历即可.

    • 其实现非常简单,只需要调用一个for循环即可。这里定义最大的页码数为100,range()方法的返回结果就是1到100的列表,顺序遍历,调用next_page(page_number)方法即可。
    • 这样我们的淘宝商品爬虫就完成了,最后调用main()方法即可运行。
    4.4.1本次循环的方法

    1)首先查看淘宝页面,使用页面跳转的方法有两种,一是使用高亮的第1页,第2页,....下一页,而是直接输入第几页
    -方法一 ,不推荐使用,具体原因如下:
    这里不直接点击“下一页”的原因是:一旦爬取过程中出现异常退出,比如到50页退出了,此时点击“下一页”时,就无法快速切换到对应的后续页面了。此外,在爬取过程中,也需要记录当前的页码数,而且一旦点击“下一页”之后页面加载失败,还需要做异常检测,检测当前页面是加载到了第几页。整个流程相对比较复杂,所以这里我们直接用跳转的方式来爬取页面。

    • 方法二,使用的方式是,直接在页面上写第几页.


    2)页面输入框

    input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input")))
    

    3)页面确定按钮

        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit")))
    

    4)首先清除页面输入框的内容:
    input.clear()#清除页码输入框的内容

    完整的代码:

    def next_page(page_number):
        print("正在翻页",page_number)
        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_number)#输入页码
            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_number)))#判断是否翻页成功,通过判断当前的页数是否正确
            get_product()
        except TimeoutException:
            next_page(page_number)
    

    4.5解析网页-商品列表-get_products()

    • 接下来,我们就可以实现get_products()方法来解析商品列表了。这里我们直接获取页面源代码,然后用pyquery进行解析
    • 首先,调用page_source属性获取页码的源代码,然后构造了PyQuery解析对象,接着提取了商品列表,此时使用的CSS选择器是#mainsrp-itemlist .items .item,它会匹配整个页面的每个商品。它的匹配结果是多个,所以这里我们又对它进行了一次遍历,用for循环将每个结果分别进行解析,每次循环把它赋值为item变量,每个item变量都是一个PyQuery对象,然后再调用它的find()方法,传入CSS选择器,就可以获取单个商品的特定内容了。
    • 可以发现,它是一个img节点,包含id、class、data-src、alt和src等属性。这里之所以可以看到这张图片,是因为它的src属性被赋值为图片的URL。把它的src属性提取出来,就可以获取商品的图片了。不过我们还注意data-src属性,它的内容也是图片的URL,观察后发现此URL是图片的完整大图,而src是压缩后的小图,所以这里抓取data-src属性来作为商品的图片。
    • 因此,我们需要先利用find()方法找到图片的这个节点,然后再调用attr()方法获取商品的data-src属性,这样就成功提取了商品图片链接。然后用同样的方法提取商品的价格、成交量、名称、店铺和店铺所在地等信息,接着将所有提取结果赋值为一个字典product,随后调用save_to_mongo()将其保存到MongoDB即可。
    1. 保存到MongoDB
    4.5.1本次解析的方法
    • 商品的代码结构,如下:


    • 判断页面商品信息是否加载成功
      wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-itemlist .items .item ")))

    • 获得页面所有选择的内容:
      items=doc('#mainsrp-itemlist .items .item').items()

    • 分析商品图片:
      "image" :item.find(".pic .img").attr("src")


    • 解析商品价格
      "price" :item.find(".price").text()


    • 解析商品成交量
      "deal" :item.find(".deal-cnt").text()[:-3]切片到倒数第三个


    • 解析商品标题
      "title" :item.find(".title").text()


    • 解析商品店铺名称
      "shop" :item.find(".shop").text()


    • 解析商品店铺地址
      "location" :item.find(".location").text()



      -完整的代码:

    # -*- coding: utf-8 -*-
    """
    Created on Sat Feb 10 18:33:26 2018
    
    @author: Administrator
    """
    import re
    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 pyquery import PyQuery as pq
    
    
    browser = webdriver.Chrome()
    wait = WebDriverWait(browser, 10)
    
    def search():
        try:
            browser.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("美食") #操作动作
            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 search()          
    
    
    def next_page(page_number):
        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_number)#输入页码
            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_number)))#判断是否翻页成功,通过判断当前的页数是否正确
            get_product()
        except TimeoutException:
            next_page(page_number)
    
    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"),
                    "price" :item.find(".price").text(),
                    "deal" :item.find(".deal-cnt").text()[:-3],#切片到倒数第三个
                    "title" :item.find(".title").text(),
                    "shop" :item.find(".shop").text(),
                    "location" :item.find(".location").text(),
                     }                    
             print(product)
                                                   
    def main():
        total=search()
        total=int(re.compile('(\d+)').search(total).group(1))
        for i in range(2,total+1):
            next_page(i)
        
    if __name__=='__main__':
        main()
    

    -最后显示的结果


    4.5.2解析的学习内容

    4.6保存在MongoDB

    这里首先创建了一个MongoDB的连接对象,然后指定了数据库,随后指定了Collection的名称,接着直接调用insert()方法将数据插入到MongoDB。此处的result变量就是在get_products()方法里传来的product,包含单个商品的信息。

    4.6.1本次保存在MongoDB的方法
    • 新建一个配置文件叫untitled2.py,并输入以下代码
    MONGO_URL ="localhost"#本地数据库
    MONGO_DB="taobao"#数据库的名称
    MONGO_TABLE="product"#数据库表的名称
    
    • 在之前的文件引入mongodb相关数据
    import re
    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 pyquery import PyQuery as pq
    from untitled2 import *#引入mongodb的配置文件
    import pymongo#引入mongodb所有的变量
    
    • 在之前的文件声明mongodb相关信息
    client=pymongo.MongoClient(MONGO_URL)
    db=client[MONGO_DB]
    
    • 在之前的文件定义mongodb方法:
    def save_to_mongo(result):
        try:
            if db[MONGO_TABLE].insert(result):
                print("存储到MONGODB成功",result)
        except Exception:
            print("存储到MONGODB失败",result)
    
    • 完整的代码为:
    import re
    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 pyquery import PyQuery as pq
    from untitled2 import *#引入mongodb的配置文件
    import pymongo
    
    client=pymongo.MongoClient(MONGO_URL)
    db=client[MONGO_DB]
    
    
    browser = webdriver.Chrome()
    wait = WebDriverWait(browser, 10)
    
    def search():
        try:
            browser.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("美食") #操作动作
            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 search()          
    
    
    def next_page(page_number):
        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_number)#输入页码
            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_number)))#判断是否翻页成功,通过判断当前的页数是否正确
            get_product()
        except TimeoutException:
            next_page(page_number)
    
    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"),
                    "price" :item.find(".price").text(),
                    "deal" :item.find(".deal-cnt").text()[:-3],#切片到倒数第三个
                    "title" :item.find(".title").text(),
                    "shop" :item.find(".shop").text(),
                    "location" :item.find(".location").text(),
                     }                    
             print(product)
             save_to_mongo(product)
    
    def save_to_mongo(result):
        try:
            if db[MONGO_TABLE].insert(result):
                print("存储到MONGODB成功",result)
        except Exception:
            print("存储到MONGODB失败",result)
    
    def main():
        total=search()
        total=int(re.compile('(\d+)').search(total).group(1))
        for i in range(2,total+1):
            next_page(i)
        browser.close()#把浏览器关掉
        
    if __name__=='__main__':
        main()
    

    配置文件

    MONGO_URL ="localhost"
    MONGO_DB="taobao"
    MONGO_TABLE="product"
    

    运行的时候,同时要将配置文件打开,才可以运行.运行的结果如下:



    4.6.2MongoDB的学习内容

    4.7使用PhantomJS

    4.7.1本次使用PhantomJS的方法
    • 因用模拟浏览器打开,有点麻烦,所以改为用PhanttomJS,,是无界面浏览器.
      将browser = webdriver.Chrome()改为browser = webdriver.PhantomJS()
    • 在untitled2.py配置文件增加:
      SERVICE_ARGS=["--load-images=false","--disk-cache=true"]#是数组形式,不加载浏览器图片,开启缓存
    • 在之前文件,增加配置文的变量引入:
      browser = webdriver.PhantomJS(service_args=SERVICE_ARGS)
    • 分别在search()/next_page(page_number)分别增加print("正在搜索")/print("正在翻页",page_number)
    • 完整的代码为:
    # -*- coding: utf-8 -*-
    """
    Created on Sat Feb 10 18:33:26 2018
    
    @author: Administrator
    """
    import re
    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 pyquery import PyQuery as pq
    from untitled2 import *#引入mongodb的配置文件
    import pymongo
    
    client=pymongo.MongoClient(MONGO_URL)
    db=client[MONGO_DB]
    
    
    browser = webdriver.PhantomJS(service_args=SERVICE_ARGS)
    wait = WebDriverWait(browser, 10)
    
    browser.set_window_size(1400,900)#设置窗口大小
    
    def search():
        print("正在搜索")
        try:
            browser.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("美食") #操作动作
            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 search()          
    
    
    def next_page(page_number):
        print("正在翻页",page_number)
        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_number)#输入页码
            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_number)))#判断是否翻页成功,通过判断当前的页数是否正确
            get_product()
        except TimeoutException:
            next_page(page_number)
    
    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"),
                    "price" :item.find(".price").text(),
                    "deal" :item.find(".deal-cnt").text()[:-3],#切片到倒数第三个
                    "title" :item.find(".title").text(),
                    "shop" :item.find(".shop").text(),
                    "location" :item.find(".location").text(),
                     }                    
             print(product)
             save_to_mongo(product)
    
    def save_to_mongo(result):
        try:
            if db[MONGO_TABLE].insert(result):
                print("存储到MONGODB成功",result)
        except Exception:
            print("存储到MONGODB失败",result)
    
                                                   
    def main():
        total=search()
        total=int(re.compile('(\d+)').search(total).group(1))
        for i in range(2,total+1):
            next_page(i)
        browser.close()#把浏览器关掉
        
    if __name__=='__main__':
        main()
    

    配置文件代码为:

    MONGO_URL ="localhost"
    MONGO_DB="taobao"
    MONGO_TABLE="product"
    
    
    SERVICE_ARGS=["--load-images=false","--disk-cache=true"]#是数组形式,不加载浏览器图片,开启缓存
    

    运行的时候,同时要将配置文件打开,才可以运行.运行的结果如下:


    4.7.2使用PhantomJS的方法

    官方网站:PhantomJS

    4.8整体代码的完善

    4.7.1本次完善代码的方法
    • 在untitled2.py配置文件增加:KEYWORD = "美食"
      然后将search()中的input.send_keys("美食")改为input.send_keys("KEYWORD")
    • 将main(),增加try 和findally
    def main():
        try:
            total=search()
            total=int(re.compile('(\d+)').search(total).group(1))
            for i in range(2,total+1):
                next_page(i)
        finally:
            browser.close()#把浏览器关掉
    

    完整的代码

    @author: Administrator
    """
    import re
    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 untitled2 import *#引入mongodb的配置文件
    import pymongo
    
    client=pymongo.MongoClient(MONGO_URL)
    db=client[MONGO_DB]
    
    
    browser = webdriver.PhantomJS(service_args=SERVICE_ARGS)
    wait = WebDriverWait(browser, 10)
    
    browser.set_window_size(1400,900)#设置窗口大小
    
    def search():
        print("正在搜索")
        try:
            browser.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("KEYWORD") #操作动作
            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 search()          
    
    
    def next_page(page_number):
        print("正在翻页",page_number)
        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_number)#输入页码
            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_number)))#判断是否翻页成功,通过判断当前的页数是否正确
            get_product()
        except TimeoutException:
            next_page(page_number)
    
    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"),
                    "price" :item.find(".price").text(),
                    "deal" :item.find(".deal-cnt").text()[:-3],#切片到倒数第三个
                    "title" :item.find(".title").text(),
                    "shop" :item.find(".shop").text(),
                    "location" :item.find(".location").text(),
                     }                    
             print(product)
             save_to_mongo(product)
    
    def save_to_mongo(result):
        try:
            if db[MONGO_TABLE].insert(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)
        finally:
            browser.close()#把浏览器关掉
        
    if __name__=='__main__':
        main()
    

    配置文件:

    MONGO_URL ="localhost"
    MONGO_DB="taobao"
    MONGO_TABLE="product"
    
    
    SERVICE_ARGS=["--load-images=false","--disk-cache=true"]#是数组形式,不加载浏览器图片,开启缓存
    KEYWORD = "美食"
    
    

    相关文章

      网友评论

      • 747071ac3c1d:你是这样查找那个搜索的button
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#J_TSearchForm > div.search-button > button")))
        我是通过这样的选择器查找的这个按钮的
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"#J_SearchForm button.submit")))
        但是我的为什么查找不到?
      • WenzhiSu:写的真详细👍👍👍
        努力奋斗的durian:@苏文知 有什么不足之处也帮忙看看哦.

      本文标题:(九)使用Selenium+Chrome/PhantomJS(模

      本文链接:https://www.haomeiwen.com/subject/xjhhtftx.html