您的位置:首页 > 编程语言 > Python开发

爬虫实战:使用selenium爬取淘宝商品 -《Python3网络爬虫开发实战》

2018-07-18 22:23 295 查看

目录

分析页面

创建browser对象:

抓取索引页:

解析商品列表

将数据储存到MongoDB数据库

定义主函数

运行代码

运行结果如下:

完整代码:

  • 分析页面

请求页面的url为:https://s.taobao.com/search?q=keyword,本次爬虫keyword为“施华洛世奇”,页面使用Ajax获取商品,但是Ajax请求中有加密参数,解密比较麻烦,所以用selenium控制浏览器来爬取

  • 创建browser对象:

这里首先构造了一个chrome浏览器对象,注意此处使用chrome-headless(无界面模式)来提高爬虫效率,又构造了一个WebDriverWait对象来等待加载,这里指定等待最大时长为5秒,如果在这个时间内成功匹配了等待条件,也就是页面元素加载出来了,就立即返回相应结果并继续向下执行,否则到了最大等待时间还没有加在出来,就抛出超时异常。

[code]chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=chrome_options)
wait = WebDriverWait(browser,5)
keyword = '施华洛世奇'
  • 抓取索引页:

使用chrome浏览器的开发者工具定位节点,此处定位的节点有:input(页码输入框),submit(提交页码按钮),item(商品节点,以及一个当前页码高亮显示的节点。如下图所示。

 

当page(页码)参数大于1(需要跳转页面)时,选定input节点,使用clear()方法清除文本框内原本的页码,使用send_keys()方法输入页码,使用click()方法点击submit按钮提交页码。当 当前页码显示高亮,以及所有item节点加载完毕时,使用browser的page_source属性将此时的页面html代码返回。实现代码如下:

[code]def index_page(page):
'''抓取索引页,参数为页码'''
print('正在抓取第{0}页'.format(page))
url = 'https://s.taobao.com/search?q='+quote(keyword)
browser.get(url)
try:
if page > 1 :
input = wait.until(EC.presence_of_element_located((By.XPATH,'//div[@id="mainsrp-pager"]//input[@aria-label="页码输入框"]')))
submit = wait.until(EC.element_to_be_clickable((By.XPATH,'//div[@id="mainsrp-pager"]//span[@class="btn J_Submit"]')))
input.clear()
input.send_keys(page)
submit.click()
except TimeoutException:
index_page(page)
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'div#mainsrp-pager li.item.active > span'),str(page)))
wait.until(EC.presence_of_element_located((By.XPATH,'//div[@id="mainsrp-itemlist"]//div[@class="items"]/div[contains(@class,"item")]')))
html = browser.page_source
return html
  • 解析商品列表

首先接收刚才index_page(page)返回的html代码,作为参数传入。构造PyQuery解析对象,接着提取商品列表。使用CSS选择器选择所有商品节点,用items()方法得到一个生成器,然后就可以使用for循环遍历每一个item节点(商品节点),每一个item变量都是一个PyQuery对象,然后就可以使用find()方法,传入CSS选择器,就可以获取单个商品的特定属性内容了。最后将商品的属性和值储存为一个字典,print出来,再调用save_to_mongo()函数(稍后定义)将数据储存到mogodb数据库。

[code]from pyquery import PyQuery

def get_products(html):
'''提取商品数据'''
doc = PyQuery(html)
items = doc('#mainsrp-itemlist .items .item').items()
for item in items:
product = {
'商品图片':'https:'+str(item.find('.img').attr('data-src')),
'价格':item.find('.price.g_price.g_price-highlight').text().replace('\n',' '),
'成交数':item.find('.deal-cnt').text(),
'商品标题':item.find('.row.row-2.title').text().replace('\n',' '),
'店铺名称':item.find('.shopname').text(),
'位置':item.find('.location').text()
}
print('\t',product)
save_to_mongo(product)
  • 将数据储存到MongoDB数据库

首先创建一个MongoDB的连接对象:client,然后指定数据库:爬虫练习,指定集合Colletion的名称为“淘宝商品”。接着调用insert方法讲数据插入到MongoDB。此处的数据就是在get_products()方法传来的商品字典。

[code]import pymongo

client = pymongo.MongoClient(host='localhost',port=27017)
db = client.爬虫练习

def save_to_mongo(product):
try:
if collection.insert(product):
print('\t\t --成功保存')
except Exception as e:
print('\t\t --保存失败\n',e)
  • 定义主函数

[code]def main(page):
html = index_page(page)
get_products(html)
  • 运行代码

使用一个for循环向主函数传入page参数。用range()函数得到页码遍历,定义最小页码为1,最大页码为页面最大页码,最大页码为上面定位的input节点中的max属性值,这里贪方便,直接定义为100(最多100页)。实现代码如下

[code]if __name__ == '__main__':
for page in range(1,101):
main(page)
  • 运行结果如下:

     

  • 完整代码:

[code]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
import pymongo

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=chrome_options)
wait = WebDriverWait(browser,5)
keyword = '施华洛世奇'

client = pymongo.MongoClient(host='localhost',port=27017)
db = client.爬虫练习
collection = db.淘宝商品

def index_page(page):
'''抓取索引页,参数为页码'''
print('正在抓取第{0}页'.format(page))
url = 'https://s.taobao.com/search?q='+quote(keyword)
browser.get(url)
try:
if page > 1 :
input = wait.until(EC.presence_of_element_located((By.XPATH,'//div[@id="mainsrp-pager"]//input[@aria-label="页码输入框"]')))
submit = wait.until(EC.element_to_be_clickable((By.XPATH,'//div[@id="mainsrp-pager"]//span[@class="btn J_Submit"]')))
input.clear()
input.send_keys(page)
submit.click()
except TimeoutException:
index_page(page)
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'div#mainsrp-pager li.item.active > span'),str(page)))
wait.until(EC.presence_of_element_located((By.XPATH,'//div[@id="mainsrp-itemlist"]//div[@class="items"]/div[contains(@class,"item")]')))
html = browser.page_source
return html

def get_products(html):
'''提取商品数据'''
doc = PyQuery(html)
items = doc('#mainsrp-itemlist .items .item').items()
for item in items:
product = {
'商品图片':'https:'+str(item.find('.img').attr('data-src')),
'价格':item.find('.price.g_price.g_price-highlight').text().replace('\n',' '),
'成交数':item.find('.deal-cnt').text(),
'商品标题':item.find('.row.row-2.title').text().replace('\n',' '),
'店铺名称':item.find('.shopname').text(),
'位置':item.find('.location').text()
}
print('\t',product)
save_to_mongo(product)

def save_to_mongo(product):
try:
if collection.insert(product):
print('\t\t --成功保存')
except Exception as e:
print('\t\t --保存失败\n',e)

def main(page):
html = index_page(page)
get_products(html)

if __name__ == '__main__':
for page in range(1,101):
main(page)

参考资料:Python3网络爬虫开发实战-崔庆才

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐