模拟登录淘宝并抓取指定商品(Selenium + pyquery + MongoDB)

The future has not been written. There is no fate but what we make for ourselves. ——《终结者3》

一切未成定局,未来等你去开创。

PS: 本文仅供学习参考、仅供学习参考、仅供学习参考,不得用于商业用途。

使用微博账号登录淘宝

  目前的淘宝,如果未登录是不能搜索商品的,如果使用淘宝的账号密码需要验证验证码,然后就想着用其他账号登录淘宝–微博账号。使用微博账号登录淘宝需要先绑定淘宝账号。步骤:登录淘宝 —— 点击你的用户名 —— 点击账号管理 —— 点击微博绑定设置,然后按照提示一步步来就好。

登录流程

代码实现

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
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class Taobao:
# 初始化
def __init__(self):
self.url = 'https://login.taobao.com/member/login.jhtml'
options = webdriver.ChromeOptions()
# options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}) # 不加载图片,加快访问速度
options.add_experimental_option('excludeSwitches', ['enable-automation']) # 设置为开发者模式,防止被各大网站识别出来使用了Selenium
self.browser = webdriver.Chrome(options=options)
self.wait = WebDriverWait(self.browser, 10) # 超时时长为10s

# 登录
def login(self, weibo_username, weibo_password):
"""
使用微博登录,避免验证
:param weibo_username: 微博用户名
:param weibo_password: 微博密码
:return:
"""
self.browser.get(self.url)
self.wait.until(EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, '微博登录'))).click() # 使用微博登录
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.username > .W_input'))).send_keys(weibo_username) # 输入账号
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.password > .W_input'))).send_keys(weibo_password) # 输入密码
self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@class="btn_tip"]/a/span'))).click() # 点击登录
# 打印淘宝会员昵称
taobao_user = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.site-nav-user > a.site-nav-login-info-nick')))
print(taobao_user.text)


if __name__ == "__main__":
weibo_username = "XXXX" # 改成你的微博账号
weibo_password = "XXXX" # 改成你的微博密码
taobao = Taobao()
taobao.login(weibo_username, weibo_password)

抓取商品

  使用selenium模拟登录后是跳转到了淘宝首页,我们可以继续模拟搜索商品以及翻页行为。

搜索商品

  在搜索框输入商品名,点击搜索

1
2
3
4
5
6
7
8
# 搜索
def search(self, kw):
"""
:param kw: 商品名
:return:
"""
self.wait.until(EC.presence_of_element_located((By.ID, 'q'))).send_keys(kw)
self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.search-button > button.btn-search.tb-bg'))).click()

翻页行为

  提取一共多少页all_page_num,提取当前页activate_page_num,如果activate_page_num小于all_page_num,模拟点击下一页,否则改变flag (isEND)。

1
2
3
4
5
6
7
8
9
10
11
12
# 下一页
def next_page(self):
try:
all_page_num = int(self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.total'))).get_attribute("innerHTML").split()[1])
activate_page_num = int(self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.item.active > span.num'))).get_attribute("innerHTML"))
if activate_page_num < all_page_num:
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.item.next a.J_Ajax.num.icon-tag'))).click()
else:
self.isEND = True
except:
time.sleep(2)
self.next_page()

解析页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 解析页面
def parse(self):
time.sleep(3)
try:
doc = pq(self.browser.page_source)
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)
self.data.extend(product)
self.next_page()
except:
time.sleep(3)
self.parse()

持久化储存至MongoDB

1
2
3
4
5
6
7
8
def save_to_mongo(self):
try:
for item in self.data:
if self.collection.update_one(item, {"$setOnInsert": item}, True):
pass
print("储存到MongoDB成功")
except Exception:
print("储存到MongoDB失败")

整合所有代码

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import time
import pymongo
from selenium import webdriver
from pyquery import PyQuery as pq
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


class Taobao:
# 初始化
def __init__(self, trade_name):
self.data = list()
self.isEND = False # 判断是否为最后一页
self.trade_name = trade_name # 要搜索的商品名及MongoDB表名
self.url = 'https://login.taobao.com/member/login.jhtml'
options = webdriver.ChromeOptions()
# options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2}) # 不加载图片,加快访问速度
options.add_experimental_option('excludeSwitches', ['enable-automation']) # 设置为开发者模式,防止被各大网站识别出来使用了Selenium
self.browser = webdriver.Chrome(options=options)
self.wait = WebDriverWait(self.browser, 10) # 超时时长为10s
client = pymongo.MongoClient('localhost')
db = client['taobao']
self.collection = db[self.trade_name]

# 登录
def login(self, weibo_username, weibo_password):
"""
使用微博登录,避免验证
:param weibo_username: 微博用户名
:param weibo_password: 微博密码
:return:
"""
self.browser.get(self.url)
self.wait.until(EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, '微博登录'))).click() # 使用微博登录
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.username > .W_input'))).send_keys(weibo_username) # 输入账号
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.password > .W_input'))).send_keys(weibo_password) # 输入密码
self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@class="btn_tip"]/a/span'))).click() # 点击登录
# 打印淘宝会员昵称
taobao_user = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.site-nav-user > a.site-nav-login-info-nick')))
print(taobao_user.text)

# 搜索
def search(self, kw):
"""
:param kw: 搜索关键字
:return:
"""
self.wait.until(EC.presence_of_element_located((By.ID, 'q'))).send_keys(kw)
self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'div.search-button > button.btn-search.tb-bg'))).click()

# 下一页
def next_page(self, page=None): # 如果不指定页码,则抓取全部
try:
if not page:
all_page_num = int(self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.total'))).get_attribute("innerHTML").split()[1])
else:
all_page_num = page
activate_page_num = int(self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.item.active > span.num'))).get_attribute("innerHTML"))
if activate_page_num < all_page_num:
self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'li.item.next a.J_Ajax.num.icon-tag'))).click()
else:
self.isEND = True
except:
time.sleep(2)
self.next_page()

# 解析页面
def parse(self):
time.sleep(3)
try:
doc = pq(self.browser.page_source)
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)
self.data.extend(product)
self.next_page()
except:
time.sleep(3)
self.parse()

# 持久化储存至MongoDB
def save_to_mongo(self):
try:
for item in self.data:
if self.collection.update_one(item, {"$setOnInsert": item}, True):
pass
print("储存到MongoDB成功")
except Exception:
print("储存到MongoDB失败")

# 主函数
def main(self):
self.search(self.trade_name)
while not self.isEND: # 循环条件 存在下一页
self.parse()
self.save_to_mongo()


if __name__ == "__main__":
weibo_username = "XXXX" # 改成你的微博账号
weibo_password = "XXXX" # 改成你的微博密码
trade_name = '梅艳芳' # 改成你想要抓取的商品
taobao = Taobao(trade_name)
taobao.login(weibo_username, weibo_password)
taobao.main()

效果展示

爬取效果

结果展示

写在最后

  梅艳芳:她,不是一两句话就能说清楚的。很多90后应该都不知道这个名字了。很多次我问我不同的朋友:你知道梅艳芳吗?他们的回答出奇的一致,梅艳芳?你说的是梅兰芳吧!我抓取了关于她的所有商品,很多都是0人付款。或许是时代在前进,属于她的时代已经往事如烟,随风飘散,人们渐渐将她遗忘。但是,我写这段话的时候她的那首《梦里共醉》仿佛依然萦绕在我的耳畔。

PS: 本文仅供学习参考、仅供学习参考、仅供学习参考,不得用于商业用途。