爬取淘宝商品

爬取淘宝商品

一、项目需求

1. 淘宝的整个页面都是由Ajax获取的,而且还包含加密参数,所以这里要使用 Selenium 来模拟浏览器爬取淘宝商品信息。

2. 将淘宝上关于ipad关键字的搜索结果爬取下来,并使用 MongoDB 储存数据。

3. 爬取的数据要包含商品的图片,名称,价格,购买人数,店铺名称和店铺地址。

 

二、项目分析

 抓取入口是淘宝的搜索页面,URL:https://s.taobao.com/search?q=iPad,如下方截图:

爬取淘宝商品_第1张图片

  可以发现,在页面下方有一个分页导航,其中既包括前5页的链接,也包括下一页的链接,同时还有一个输入任意页码跳转的链接,这里商品的搜索结果为100页,要获取每一页的内容,只需要将页码从1到100顺序遍历即可,页码数是确定的。所以,直接在页面跳转文本框中输入要跳转的页面,然后点击确定按钮即可跳转到页码对应的页面了。可能你会问为什么不直接点下一页,因为一旦爬取过程中出现异常退出,比如到50页退出了,此时点击下一页时,就无法快速切换到对应的后续页面了。此外,在爬取过程中,也需要记录当前的页码数,而且一旦点击下一页之后页面加载失败,还需要做异常检测,检测当前页面是加载到第几页,整个流程相对复杂,所以这里使用简单粗暴的方法,直接获取输入框然后在里面输入页码,最后通过点击按钮实现跳转。接下来就可以使用 Selenium 抓取了:

 1 from selenium import webdriver
 2 from selenium.common.exceptions import TimeoutException
 3 from selenium.webdriver.common.by import By
 4 from selenium.webdriver.support import expected_conditions as EC
 5 from selenium.webdriver.support.wait import WebDriverWait
 6 from urllib.parse import quote
 7 
 8 
 9 browser = webdriver.Chrome()
10 wait = WebDriverWait(browser,10)
11 KEYWORD = 'iPad'
12 
13 
14 def index_page(page):
15     """抓取索引页"""
16     print('正在抓取第' + page + '')
17     try:
18         url = 'https://s.taobao.com/search?q=' + quote(KEYWORD)
19         browser.get(url)
20         if page > 1:
21             input = wait.until(
22                 EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager div.form > input')))
23             submit = wait.until(
24                 EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager div.form > span.btn.J_Submit')))
25             input.clear()
26             submit.click()
27         wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page)))
28         wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'.m-itemlist .items .item')))
29         get_products()
30     except TimeoutException:
31         index_page(page)

  这里先构造了一个WebDriver对象,指定关键字‘iPad’,接着定义了index_page()方法用于抓取商品页面。在该方法里,首先访问了搜索商品的链接,然后判断了当前的页码,如果大于1,就进行跳转页面操作,否则等待页面加载完成。等待加载时,使用了WebDriverWait对象,它可以指定等待条件,同时指定一个最长等待时间,这里指定为10秒。如果在这个时间内成功匹配了等待条件,也就是说页面元素成功加载出来了,就立即返回相应结果并继续向下执行,否则到了最大等待时间还没有加载出来时,就直接抛出超时异常。关于翻页的操作,这里首先获取页码输入框,赋值为input,然后获取确定按钮,赋值为submit。然后清空了输入框的内容,再调用send_keys()方法将页码填充到输入框中,然后点击确定按钮。然而这里有一个问题就是,我们怎么知道有没有跳转到对应的页码呢?可以注意到,如果我们在某一页,当前的页码是会高亮显示的,所以只需要判断当前高亮的页码数是当前的页码数即可,然而这里使用了另外一个等待条件text_to_be_present_in_element,它会等待指定的文本出现在某一个节点里面时即返回成功。这里我们将高亮的页码节点对应的CSS选择器和当前要跳转的页码通过参数传递给这个等待条件,这样就会检测当前高亮的页码节点是不是我们传过来的页码数,如果是,就证明页面跳转成功了。接下来就可以实现get_products()方法来解析商品了:

 1 def get_products():
 2     html = browser.page_source
 3     document = pq(html)
 4     items = document('#mainsrp-itemlist .items .item').items()
 5     for item in items:
 6         product = {
 7             'image':item.find('.pic .img').attr('data-src'),
 8             'price':item.find('.price').text(),
 9             'deal':item.find('.deal-cnt').text(),
10             'shop':item.find('.shop').text(),
11             'location':item.find('.location').text(),
12         }
13         print(product)
14         save_to_mongo(product)

首先,调用page_source属性获取页面源码,然后构造了PyQuery解析对象,接着提取了商品列表,此时使用的CSS选择器是#mainsrp-itemlist .items .item,它会匹配整个页面的每个商品。它的匹配结果是多个,所以这里我们又对它进行一次遍历,用for循环将每个结果分别进行解析,每次循环把它赋值为item变量,每个item变量都是一个PyQuery对象,然后再调用它的find()方法,传入CSS选择器,就可以获取单个商品的特定内容了。最后的工作就是讲我们需要的数据保存到 MongoDB 中了。

 

三、项目源码

 1 from selenium import webdriver
 2 from selenium.common.exceptions import TimeoutException
 3 from selenium.webdriver.common.by import By
 4 from selenium.webdriver.support import expected_conditions as EC
 5 from selenium.webdriver.support.wait import WebDriverWait
 6 from urllib.parse import quote
 7 from pyquery import PyQuery as pq
 8 import pymongo
 9 
10 
11 browser = webdriver.Chrome()
12 wait = WebDriverWait(browser,10)
13 KEYWORD = 'iPad'
14 MAX_PAGE = 100
15 
16 MONGO_URL = 'localhost'
17 MONGO_DB = 'taobao'
18 MONGO_COLLECTION = 'products'
19 client = pymongo.MongoClient(MONGO_URL)
20 db = client[MONGO_DB]
21 
22 
23 def index_page(page):
24     print('now is ',page)
25     try:
26         url = 'https://s.taobao.com/search?q=' + quote(KEYWORD)
27         browser.get(url)
28         if page > 1:
29             input = wait.until(
30                 EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager div.form > input')))
31             submit = wait.until(
32                 EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager div.form > span.btn.J_Submit')))
33             input.clear()
34             input.send_keys(page)
35             submit.click()
36         wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager li.item.active > span'),str(page)))
37         wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'.m-itemlist .items .item')))
38         get_products()
39     except TimeoutException:
40         index_page(page)
41 
42 
43 def get_products():
44     html = browser.page_source
45     document = pq(html)
46     items = document('#mainsrp-itemlist .items .item').items()
47     for item in items:
48         product = {
49             'image':item.find('.pic .img').attr('data-src'),
50             'price':item.find('.price').text(),
51             'deal':item.find('.deal-cnt').text(),
52             'shop':item.find('.shop').text(),
53             'location':item.find('.location').text(),
54         }
55         print(product)
56         save_to_mongo(product)
57 
58 
59 def save_to_mongo(result):
60     try:
61         if db[MONGO_COLLECTION].insert(result):
62             print('success')
63     except Exception:
64         print('fail')
65 
66 
67 def main():
68     for i in range(1,MAX_PAGE+1):
69         index_page(i)
70 
71 
72 if __name__ == '__main__':
73     main()

转载于:https://www.cnblogs.com/jonas-von/p/9209981.html

你可能感兴趣的:(爬取淘宝商品)