前言 前面介绍了使用selenium和chromedriver通过模拟浏览器运行的方式可以做到在浏览器中看到是什么样,抓取的源码就是什么样。不用再去管网页内部的JavaScript是如何渲染页面,也不用管网页后台的Ajax接口有哪些参数,甚至是加密规律等。这篇博客是实战演练,通过Selenium爬取淘宝网商品的图片,名称,价格,购买人数,店铺名称,店铺所在地信息,将结果保存至Mongodb数据库中。
Chromedriver for linux 上一篇博客只介绍了chromedriver在windows下的安装
http://yhch.xyz/2018/07/08/Python3%E7%88%AC%E8%99%AB-selenium-chromedriver%E5%8F%AF%E8%A7%81%E5%8D%B3%E5%8F%AF%E7%88%AC/ 
对应版本的下载和测试安装是方法是一样的
1 2 3 4 5 6 7 8 9 10 11 12    //解压 unzip chromedriver_linux64.zip //移动到环境变量所在的目录 sudo mv chromedriver /usr/bin //或者将chromedriver所在目录,添加到环境变量 export PATH="$PATH:所在目录" //执行新的配置 source ~/.porfile 
   
分析一波 1.ajax请求分析 
_ksTS,rn 这两个参数很难发现其规律,所以这里不采用构造Ajax请求的方式来爬取内容,而通过selemium价格网页最终呈现效果的HTML代码全部爬取下来,再来提取所要信息
2.商品分析  需要说明的是src  和data-src 都是商品图片的网络地址,区别是前者是缩略图而后者是高清大图,两者都可以任意爬取,这里爬取的是后者
3.页码分析 
这里不点击下一页,而是通过自动输入页面数来进行页面跳转,一方面是要实时监控爬取到多少页,另一方面,当程序出现异常,下一次运行又从第一页开始,下一页依次爬取,数据库中,会有重复记录
code 1. 获取商品列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42    import pymongo from selenium import webdriver from selenium.common.exceptions import  TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from urllib.parse import quote from pyquery import  PyQuery as pq driver = webdriver.Chrome() wait = WebDriverWait(driver,10) KEYWORD = 'iMac' def index_page(page):     print('正在爬取第',page,'页')      try:         url = 'https://s.taobao.com/search?q='+quote(KEYWORD)         driver.get(url)          if page > 1:             input = wait.until(                 EC.presence_of_element_located((By.CSS_SELECTOR,                                                  '#mainsrp-pager    div.form > input')))             submit = wait.until(                 EC.presence_of_element_located((By.CSS_SELECTOR,                                          '#mainsrp-pager div.form > span.btn.J_Submit')))             input.clear()              input.send_keys(page)             submit.click()          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()      except TimeoutException:         index_page(page)       
   
通过构造查询参数,得到淘宝网的搜索URLhttps://s.taobao.com/search?q=iMac  ,q 后面接你要搜索的关键词。就能够跳转到搜索指定商品后的页面,也是程序的入口URL 通过改变EYWORD 的值,就能爬取不同商品信息;拼接URL的时候用到quote 方法,屏蔽特殊字符串,如空格等,URL地址里是不含空格的,同时将字符串转换为URL编码格式,以保证URL的正确性。
下面代码等待加载时,使用了WebDriverWait对象,指定等待条件和10s的最长等待时间,如果在这个时间内页面元素成功加载出来了,就相应结果并继续向下执行,否则抛出超时异常。EC.presence_of_element_located 是元素成功加载出来,EC.presence_of_element_located  意思是元素可以点击,因为它是一个按钮,这个按钮的作用是选定页码后的点击确定后跳转。
为了验证跳转到了对应的页码,需要判断当前高亮的页码数是当前的页码数(当前所在页码会高亮显示,也就是说当前页码的css是特殊的),所以这里使用了另一个等待条件text_to_be_present_in_element ,它会等待指定的文本出现在某一个节点里面时即返回成功。这里我们将高亮的页码节点对应的CSS选择器和当前要跳转的页码通过参数传递给这个等待条件,这样它就会检测当前高亮的页码节点是不是我们传过来的页码数,如果是,就证明页面成功跳转到了这一页,页面跳转成功。
这样刚才实现的index_page()方法就可以传入对应的页码,待加载出对应页码的商品列表后,再去调用get_products()方法进行页面解析。
这些等待条件的参数都是特定的css选择器,不做赘述了,图片已经标注的很清楚了
2.解析商品列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20    def get_products():     html = driver.page_source     doc = pq(html)     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)         print('\n')               
   
通过driver.page_source  获得了不同页码下完整html源码;同时使用Pyqurey来解析网页,通过已经查找的标签,查找这个标签下的子标签或者父标签,而不用从头开始查找,效率更高;通过find(css).属性 方法,获取图片URL,和其他文本信息并构造成Json字符串,调用save_to_mongo 函数存入数据库中。
3.将结果保存到Mogodb中 1 2 3 4 5 6 7 8 9 10 11 12 13 14    def save_to_mongo(result):     client = pymongo.MongoClient('mongodb://admin:admin123@localhost:27017/')     db = client['taobao']     collection = db['products']     try:          if collection.insert(result):             print("成功保存到MongoDB")      except Exception:         print('someing wrong with MongDB')         
               
python3通过认证方式连接Mongodb数据库,admin 是我的用户名,admin123 是我的密码,接着指定数据库和集合,调用insert 方法插入数据。
4.定义爬取页数 1 2 3 4 5 6 7 8 9    def  main () :     MAX_PAGE = 100      for  i in  range(1 ,MAX_PAGE+1 ):          index_page(i)     driver.close() if  __name__  =='__main__' :     main() 
        
简单for循环,并通过range生成1到100的数传递给index_page 函数。
5.完整代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79    import  pymongofrom  selenium import  webdriverfrom  selenium.common.exceptions import   TimeoutExceptionfrom  selenium.webdriver.common.by import  Byfrom  selenium.webdriver.support import  expected_conditions as  ECfrom  selenium.webdriver.support.wait import  WebDriverWaitfrom  urllib.parse import  quotefrom  pyquery import   PyQuery as  pqdriver = webdriver.Chrome() wait = WebDriverWait(driver,10 ) KEYWORD = 'iMac'  def  index_page (page) :    print('正在爬取第' ,page,'页' )     try :         url = 'https://s.taobao.com/search?q=' +quote(KEYWORD)         driver.get(url)         if  page > 1 :             input = wait.until(                 EC.presence_of_element_located((By.CSS_SELECTOR,                                                 '#mainsrp-pager    div.form > 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()         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()     except  TimeoutException:         index_page(page) def  get_products () :    html = driver.page_source     doc = pq(html)     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)         print('\n' ) def  save_to_mongo (result) :    client = pymongo.MongoClient('mongodb://admin:admin123@localhost:27017/' )     db = client['taobao' ]     collection = db['products' ]     try :         if  collection.insert(result):             print("成功保存到MongoDB" )     except  Exception:         print('someing wrong with MongDB' )          MAX_PAGE = 100  def  main () :    for  i in  range(1 ,MAX_PAGE+1 ):         index_page(i)     driver.close() if  __name__ =='__main__' :    main()     
   
小结 这段程序是对以前所学知识的综合利用,Mongodb是前几天现学现用,这是我第一次使用,关系型数据库Oracle,Sql server,Mysql 都用过,基本知识也有掌握,非关系型数据库 Mongodb以后可能会写几篇学习笔记
运行结果 1,输出结果 
2.查看mongodb中存入的数据