需要用到的有

Selenium + Chrome/PhantomJS

PhantomJS : 无界面浏览器
用的解析器: Pyquery
存储用的: MongoDB

分析页面

  1. 打开 taobao.com,并搜索 “美食”
  2. 检查页面,打开 Network 并勾选 preserve log
  3. 选择 preview 选项卡,在代码里面我们看不到任何商品的信息。

    整体流程

    首先用 Selenium模拟浏览器获取页面,然后选择搜索框并且输入“美食”并且搜索,然后在尾部输入 数字 翻页。

    Selenium with Python 等待

    http://selenium-python.readthedocs.io/waits.html

    MongoDB 安装与配置

    不用关心表的结构,直接将字典结构的动态数据直接插入就好了。

    安装

    ``` brew install mongodb
  1. ### 启动

brew services start mongodb

  1. ### 进入

mongo

  1. ### 可视化管理软件
  2. [https://www.mongodb.com/](https://www.mongodb.com/)
  3. ## PhantomJS无界面浏览器安装
  4. ### 安装

brew install phantomjs

  1. ### 配置环境变量
  2. 理论上是会直接把环境变量安装到 `/usr/local/bin`, 但是由于我们用的虚拟环境。 所以需要查看 **替身文件** 所连接的源文件拷贝到 虚拟环境的文件夹里面的 `bin` 文件夹内。<br />![20171027150907344569600.png](http://7.feilongs.com/20171027150907344569600.png)<br />**或者**到官网 [http://phantomjs.org/download.html](http:_phantomjs.org_download) 下载文件,再把安装包里面的文件夹`bin` 连的 文件拷贝到 虚拟环境里面的 `bin`文件夹内。
  3. ### 配置参数
  4. [http://phantomjs.org/api/command-line.html](http:_phantomjs.org_api_command-line)<br />可以设置例如: 是否加载图片(不加载提高速度) , 使用缓存 等等。<br />![20171027150907363298432.png](http://7.feilongs.com/20171027150907363298432.png)
  5. ## 完整代码+说明
  6. ### sipier.py

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 # 导入 PyQuery 并重命名为 pq from config import * # 引入 config.py 里面的所有变量 import pymongo

client = pymongo.MongoClient(MONGO_URL) db = client[MONGO_DB] #链接到 MONGODB

browser = webdriver.PhantomJS() # 调用 PhantomjS 浏览器, 调试阶段用chrome。调试好了就用PhantomjS 无界面浏览器 wait = WebDriverWait(browser, 10) # 浏览器等待传入 wait

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’)))

  1. # 拿到搜索按钮
  2. input.send_keys(KEYWORD) # 在这里搜索(KEYWORD),keyword 在config.py里面,在搜索框输入"美食"
  3. submit.click() # 点击搜索按钮
  4. total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.total')))
  5. # 等待元素(下面的页码显示区块)加载完成
  6. get_products() #页面完全加载好了后再调用 这个函数。此函数在下面。
  7. return total.text #获取加载完成的页码区块的字符串
  8. except TimeoutException: # 假如上面的操作失败
  9. return search() # 重新再执行一次 def 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’)))

  1. # 拿到页码后面的 确定 按钮
  2. input.clear() # 清除页码输入框的内容
  3. input.send_keys(page_number) #输入页码
  4. submit.click() # 点击确定按钮,执行翻页操作
  5. 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)))
  6. # 判断上面的翻页操作是否成功,用到函数 —— 在元素中有这样的文字(text_to_be_present_in_element),当翻页成功后,判断当前的高亮页码的文字, str(page_number) 为当前要传入判定的text,用这个页码和 CSS 选择器里面你的 text 比较
  7. get_products() # 翻页成功后再调用一下。
  8. except TimeoutException:
  9. next_page(page_number) # 如果出错就从新执行这个请求

def get_products(): # 这个函数需要在 search() 加载完是用一次,每次 next_page(page_number) 加载完一个新的页面调用一次。 wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ‘#mainsrp-itemlist .items .item’)))

  1. # 判断加载成功,id 为mainsrp-itemlist 里面的 class items 里面的 item。 如果通过了就表示所有的宝贝信息都已经加载成功了
  2. html = browser.page_source # 拿到正在网页的源代码
  3. doc = pq(html) # 把网页的源代码传入 doc
  4. items = doc('#mainsrp-itemlist .items .item').items() # 后面调用 .items() 可以选着 doc 里面的所有 .item ,每个item是一个宝贝信息
  5. for item in items:
  6. product = {
  7. 'image': item.find('.pic .img').attr('src'), #从上面的代码获取图片(获取 class .pic 里面的.img 的属性(attr) src
  8. 'price': item.find('.price').text(), # 从 class .price 里面获取 text
  9. 'deal': item.find('.deal-cnt').text()[:-3], # 从class deal-cnt 里面获取 text(去掉后面3个字符)
  10. 'title': item.find('.title').text(), # 从名称为 title 的class 里面获取 text
  11. 'shop': item.find('.shop').text(), #从 名称为 shop 的class里面获取 text
  12. 'localtion': item.find('.location').text() #从名称为 localtion 的 class 里面获取 text
  13. }
  14. print(product) # 打印单个商品信息
  15. save_to_mongo(product) #保存单个商品信息到 MONGODB

def save_to_mongo(result): # 定义保存到 MONGODB 的函数,传入 result try: # 错误判断 if db[MONGO_TABLE].insert(result): print(‘保存到 MONGO_DB成功’, result) except Exception: #如果出错就答应下面的文字+ result(result 是 product) print(‘存储到mongodb 错误’, result)

def main(): try: total = search() total = int(re.compile(‘(\d+)’).search(total).group(1)) for i in range(2, total + 1): # 页码从第2页开始,然后是3、4、5。因为一打开就是第1页 next_page(i) except Exception: #如果出错就给错误信息 print(‘错误啦’) finally: # 不论是否出现异常,最后都要执行下面的操作 browser.close()

if name == ‘main‘: main()

  1. ### config.py

MONGO_URL = ‘localhost’ MONGO_DB = ‘taobao’ MONGO_TABLE = ‘product’

SERVICE_ARGS = [‘—load-images=false’, ‘—disk-cache=true’]

http://phantomjs.org/api/command-line.html

KEYWORD = ‘美食’

```