selenium 实战爬取淘宝信息-excepted_conditions和WebDriverWait

selenium 高级用法--excepted_conditions和WebDriverWait
看了崔静觅大大的博客,这里算是写出自己对内容的一些理解还有一个实操的小项目:
selenium爬取淘宝商品
另外附上另一篇
selenium爬取京东商品

环境: python3, pymongo, selenium, Chromedrive,chrome浏览器, pyquery,mongo数据库
先说一下爬虫的思想:
对于淘宝来说使用了js进行加密数据,我们这里使用可见即可爬的工具selenium进行爬取,过程如下:

分析请求-> 找到目标信息-> 构造请求-> 提取信息-> 自动执行(翻页)

整个小demo有4个函数:

  • save_to_mongo()
    储存数据的接口
  • get_products()
    获取每页商品的信息
  • index_page()
    判断是否加载,执行完成后推送给页面分析
    *main()
    实现翻页功能
    这里会详细介绍每行代码的意义,上代码:
import pymongo
from selenium import webdriver
from selenium.common.exceptions import TimeoutException  # 超时错误
from selenium.webdriver.common.by import By   # 选择方式的模块
from selenium.webdriver.support.wait import WebDriverWait  # 显示等待
from selenium.webdriver.support import expected_conditions as EC # 条件支持
from urllib.parse import quote  # 屏蔽特殊字符
from pyquery import PyQuery as pq  # pyquery 查找分析节点

# 创建一个谷歌浏览器对象
browser = webdriver.Chrome()  
# 设置等待时间最长为3s
wait = WebDriverWait(browser, 3)
# 搜索关键字,可以整合到config文件里
KEYWORDS = 'iphone'
# mongo的地址,这里可以使用远端的地址,实现分布式
MONGO_URL = 'localhost'
# 数据库名字
MONGO_DB = 'taobao'
# 数据库集合
MONGO_COLLECTION = 'products'
# 创建一个数据库对象
client = pymongo.MongoClient(MONGO_URL, 27017)
# 指定数据库名
db = client.taobao
# 指定爬取页码
MAX_PAGE = 100


def save_to_mongo(result):
    '''
    把结果保存起来
    :param result: 解析过后的商品信息
    :return:
    '''
    try:
        if db[MONGO_COLLECTION].insert(result):  # 这里使用了插入操作,更详细的应该是有去重回滚等操作这里不做演示
            print('save result successfully')
    except Exception:
        print('fail to save')


def get_products():
    '''
    提取商品的数据
    :return:
    '''
    html = browser.page_source # 提取渲染过后的源码
    doc = pq(html)  # 创建pyquery对象,用于css选择器来提取信息
    items = doc('#mainsrp-itemlist .items .item').items()
    for item in items:
        # 提取商品的信息
        product = {  
            'image': item.find('.pic .img').attr('data-src'), 
            'price': item.find('.price').text(),
            'deal': item.find('.deal-cnt').text(),
            'title': item.find('.title').text(),
            'shop': item.find('.shop').text(),
            'location': item.find('.location').text()
        }
        print(product)
        # 传送给储存功能函数 
        save_to_mongo(product)


def index_page(page):
    '''
    抓取索引页
    :param page:页码
    :return:
    '''
    print('正在爬取第{}页...'.format(page))
    url = 'https://s.taobao.com/search?q=' + quote(KEYWORDS)
    browser.get(url)
    print(page)
    if page > 1:
        print(page)
        input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager div.form > input')))  # 指定商品页面元素加载出来就继续往下执行,如果到时间没有加载会直接报错
        print(input)
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager div.form > span.btn.J_Submit'))) # 当选择的节点可以被点击的时候我们才继续往下走,超时报错
        input.clear() # 清理输入框
        input.send_keys(page) # 键入值
        submit.click() # 点击操作
        print('done')
    wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page))) # 等待指定的文本出现在某一个节点
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item')))
    get_products() # 等待指定的元素加载出来就可以继续往下执行否则报错



def main():
    for i in range(1, MAX_PAGE + 1):
        index_page(i)


if __name__ == '__main__':
main()

感兴趣的可以把这个在电脑上运行一下试试,看看会得到什么.
另外 Chrome从59版本开始,支持无界面模式 Headless 模式,启用方式:

chrome_options = wedriver.ChromeOptions()
chrome_options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=chrome_options)

感兴趣的同学可以把浏览器换成Firefox和PhantomJs试试,PhantomJs支持禁用图片加载功能,可以进一步提高爬虫效率

SERVICE_ARGS = ['--load-images=false','--disk-cache=true']
browser = webdriver.PhatomJs(service_args= SERVICE_ARGS)

整个例子到这里结束了,我们来看下里面关于selenium等待的和条件判断的两个方法

excepted_conditions
selenium.webdriver.support.expected_conditions(模块)
用于判断用户的传入的模块是否符合我们的需求,比如上面例子里写的,是否加载完成是否可见都可以作为判断标准,用于判断页面加载进度是否达到了我们的爬去需求.更多详细的方法看这里 第7点,关于等待的用法.

WebDriverWait

  • 参数:
    WebDriverWait(driver, timeout, poll_frequency, ignored_exceptions)

driver: 传入WebDriver实例,即我们上例中的driver
timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间)
poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒
ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,
则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。

  • 等待方式
    .until(method, message)
    until

method: 在等待期间,每隔一段时间(init中的poll_frequency)调用这个传入的方法,直到返回值不是False
message: 如果超时,抛出TimeoutException,将message传入异常

not_until
与上方信息操作相反
这里注意的一点就是method参数,这个参数一定是可以调用的,一定要有 call() 方法,否则会抛出异常

综上所写,那么完整的方式应该是下面的结构

WebDriverWait(driver, timeout, poll_frequency, ignored_exceptions).until(method, message)

具体的实现方式就像例子里一样, 等待配合判断来进行爬虫的操作可以,缩短爬虫的等待时间实现爬虫的效率的最大化,极大的提高爬虫的效率.

感谢崔静觅大大的教程!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容