用Selenium抓取Steam饰品价格

用Selenium抓取Steam饰品价格

最近想从Buff上爬取所有Pubg饰品的价格、但是Buff上的饰品价格都是动态加载、当然我们有很多办法来抓取动态数据、而Selenium就是其中一个非常简单可行的方案。

Selenium是一个自动化测试工具

用浏览器官方提供的API接口来模拟操作浏览器;它支持各种主流浏览器(包括Chrome、Firefox、IE、Safari);
所有人在浏览器上的行为都可以用Selenium来驱动浏览器操作完成
所以我们也是可以用Selenium来爬取动态网站上的数据。

用Selenium抓取网页内容步骤如下

1、打开浏览器
2、访问Url地址
3、获取所需要的内容
4、关闭浏览器

最简单的实现代码

from selenium import webdriver
import time

#Buff上Pubg饰品价格
for x in range(1,13):
       url = ('https://buff.163.com/market/?game=pubg#tab=selling&page_num=%s&sort_by=price.desc' % x)
    print(url)
    driver = webdriver.Firefox()
    driver.get(url)
    try:
        for i in range(1,21):
            name = driver.find_element_by_xpath(
                ('//html/body/div[6]/div/div[4]/div[1]/ul/li[%s]/h3/a') % i)
            money = driver.find_element_by_xpath(
                ('//html/body/div[6]/div/div[4]/div[1]/ul/li[%s]/p/strong') % i)
            print(name.text,money.text)
    except:
        pass

    driver.close()

上面这段代码我用xpath来定位并获取到Buff上的Pubg饰品名称和对应的价格;

如果你仔细看这段代码的话、会发现、一共需要访问12个页面获取数据;也就是说需要打开12次浏览器并关闭!
这段代码运行完之后耗时120s左右;

接下来我们想优化一下爬虫性能;能不能只打开一次浏览器;然后抓取完一个url之后不关闭浏览器的情况下访问下一个url地址;

修改之后的代码

from selenium import webdriver
import time

#Buff上Pubg饰品价格
driver = webdriver.Firefox()
for x in range(1,13):
    url = ('https://buff.163.com/market/?game=pubg#tab=selling&page_num=%s&sort_by=price.desc' % x)
    print(url)
    #driver = webdriver.Firefox()
    driver.get(url)
    try:
        for i in range(1,21):
            name = driver.find_element_by_xpath(
                ('//html/body/div[6]/div/div[4]/div[1]/ul/li[%s]/h3/a') % i)
            money = driver.find_element_by_xpath(
                ('//html/body/div[6]/div/div[4]/div[1]/ul/li[%s]/p/strong') % i)
            print(name.text,money.text)
    except:
        pass

driver.close()

上面的代码只是简单的把打开浏览器的操作driver = webdriver.Firefox()提前到for循环之前;
这样的结果就是只打开一次浏览器、并且会逐一的访问url地址;
但是运行代码之后却发现、只获取到了第一页里面的数据;并且重复获取了12次第一页的数据。

也就是说虽然在同一个浏览器窗口里面打开了不同的url地址、但是获取到的内容却一直是第一个url里面的数据。

从现象分析之后可以确定、虽然我们在同一个浏览器窗口里面打开了url地址、但是却没有刷新页面内容、导致页面上一直显示的数据就是第一个url里面的数据。
知道了问题所在之后就好解决了。

最终的代码

#!/usr/bin/env python
#encoding = utf-8
from selenium import webdriver
import time

#Buff上Pubg饰品价格
driver = webdriver.Firefox()
for x in range(1,13):
    url = ('https://buff.163.com/market/?game=pubg#tab=selling&page_num=%s&sort_by=price.desc' % x)
    print(url)
    #driver = webdriver.Firefox()
    driver.get(url)
    driver.refresh()
    try:
        for i in range(1,21):
            name = driver.find_element_by_xpath(
            ('//html/body/div[6]/div/div[4]/div[1]/ul/li[%s]/h3/a') % i)
            money = driver.find_element_by_xpath(
            ('//html/body/div[6]/div/div[4]/div[1]/ul/li[%s]/p/strong') % i)
            print(name.text,money.text)
    except:
        pass

driver.close()

有没有发现我们只需要在seleniumget(url)方法后面调用一下refresh()来强制刷新下网页就可以完美的解决了我们上面遇到的问题。

运行第一份代码;耗时120s、运行第三份代码耗时35s;我们只是稍微的修改了一下代码、性能提升超过3倍!

抓取Steam的饰品价格Github地址:获取Steam饰品价格