淘宝的页面也是通过Ajax来抓取相关数据,但是参数比较复杂,甚至包含加密秘钥。使用selenium来模拟浏览器操作,抓取淘宝商品信息,即可做到可见即可爬。
1.准备工作
用selenium抓取淘宝商品,并用pyquery解析得到商品的图片,名称,价格,购买人数,店铺名称和店铺所在位置。
即需要安装selenium,pyquery,以及Chrome浏览器并配置ChromeDriver。
2.页面分析
我们的目标是获取商品的信息,那么先搜索,例如我们搜索美食。即可直接访问https://s.taobao.com/search?q=美食,得到第一页商品信息。如下图:
而我们需要的信息都在每一页商品条目里。如下图:
在页面的最下面,有个分页导航。为100页,要获得所以的信息只需要从第一页到带一百页顺序遍历。采用selenium模拟浏览器不断的遍历即可得到,这里为直接输入页数然后点击确定转跳。这样即使程序中途出错,也可以知道爬到那一页了,而不必从头再来。如下图:
如上图,我们爬取淘宝商品信息,只需要得到总共多少条商品条目,而淘宝默认100页,则只需要每一页商品条目都加载完之后爬取,然后再转跳就好了。用selenium只需要定位到专业和条目即可。
3.爬取每一页
首先构造https://s.taobao.com/search?q=美食,我们将美食定义成变量。则可爬取想要的商品。将要爬取的页数当做参数传入,在方法里我们先访问了搜素商品的链接,然后判断当前页数,如果大于1,就转跳。否则等待加载完成。这里我们使用显示等待,WebDriverWait对象,指定一个最长等待时间。如果在等待时间里匹配了等待条件,则返回结果继续向下执行。我们需要的是等待商品信息加载出来,使用presence_of_element_located这个条件。如果加载成功,则执行后续的get_products()方法。
转跳先定位跳转条目,然后clear()清空输入框,然后使用send_keys()将页码传入输入框,最后点击确定。在跳转那里可以观察到成功跳转到某一页后,页码会高亮显示。这里使用text_to_be_present_in_element()方法判断需要的页码是否出现在高亮的节点里。代码如下:
代码语言:javascript复制def index_page(page):
"""
抓取索引页:param page:页码
"""
print('正在爬取第', page, '页')
try:
url = 'https://s.taobao.com/search?q=' quote(KEYWORD)
browser.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)
4.解析商品列表
这里我是直接用Chrome浏览器里面指着商品条目点检查得到的定位如下图:
代码如下:
代码语言:javascript复制def get_products():
'''
提取商品
'''
html = browser.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)
5.保存到MongoDB
代码如下:
代码语言:javascript复制MONGO_URL = 'localhost'
MONGO_DB = 'taobao'
MONGO_COLLECTION = 'foods'
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
def save_to_mongo(result):
"""
保存至MongoDB
"""
try:
if db[MONGO_COLLECTION].insert(result):
print('存储到MongoDB 成功')
except Exception:
print('存储到MongoDB失败')
6.运行结果
7.总结
基本上实现了可见及可爬,我也是爬虫小新手工科研究生在读。如果考研或者python想要共同学习的请大家多多关照,如有错误请多多指教。下面附上完整代码。期待与大家共同进步。
8.完整代码
代码语言:javascript复制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
import pymongo
MAX_PAGE = 100
MONGO_URL = 'localhost'
MONGO_DB = 'taobao'
MONGO_COLLECTION = 'foods'
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
browser = webdriver.Chrome()
wait = WebDriverWait(browser, 10)
KEYWORD = '美食'
def index_page(page):
"""
抓取索引页:param page:页码
"""
print('正在爬取第', page, '页')
try:
url = 'https://s.taobao.com/search?q=' quote(KEYWORD)
browser.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 = browser.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)
def main():
'''
遍历每一页
'''
for i in range(1, MAX_PAGE 1):
index_page(i)
browser.close()
def save_to_mongo(result):
"""
保存至MongoDB
"""
try:
if db[MONGO_COLLECTION].insert(result):
print('存储到MongoDB 成功')
except Exception:
print('存储到MongoDB失败')
if __name__ == '__main__':
main()