在上一篇文章Python采集淘宝商品并存入MongoDB数据库中,使用了微博账号登陆淘宝采集数据的方式。但这种方法爬取了十几页之后就可能出现验证码,且手动滑动滑块验证码之后还不一定能验证通过,十分影响效率。
这次介绍另一种更强大一些的方法。首先人工登陆淘宝,登陆信息会被记录在谷歌浏览器用户数据User Data文件夹中。这个文件夹位于C盘用户→AppData→Local→Google→Chrome文件夹下。例如,我的电脑这个文件夹的完整路径为C:\Users\Lenovo\AppData\Local\Google\Chrome\User Data。
将这个User Data文件夹复制到抓取淘宝店铺Python文件(TaoBaoShopSpider.py)所在的同一文件夹下,如下图所示。然后在TaoBaoShopSpider.py文件中设置--user-data-dir属性,指向User Data文件夹,即:
chrome_options.add_argument('--user-data-dir=User Data')
为什么--user-data-dir不直接指向C:\Users\Lenovo\AppData\Local\Google\Chrome\User Data文件夹,而非得复制一份呢?这是因为直接指向会出现“selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: user data directory is already in use, please specify a unique value for --user-data-dir argument, or don't use --user-data-dir”的错误,导致代码不能正常运行。
完整代码如下:
import pymongo,time,random
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 pyquery import PyQuery as pq
from urllib.parse import quote
MONGO_URL = 'localhost'
MONGO_DB = 'shops'
MONGO_COLLECTION = 'zongzi'
KEYWORD = '粽子'
MAX_PAGE = 100
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_options.add_experimental_option('useAutomationExtension', False)
# chrome_options.add_argument('--headless')
# chrome_options.add_argument('--user-data-dir=C:\\Users\\Lenovo\\AppData\\Local\\Google\\Chrome\\User Data')
chrome_options.add_argument('--user-data-dir=User Data')
browser = webdriver.Chrome(chrome_options=chrome_options)
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
wait = WebDriverWait(browser, 30)
def slide_down(second):
for i in range(int(second / 0.1)):
js = "var q=document.documentElement.scrollTop=" + str(300 + 200 * i)
browser.execute_script(js)
time.sleep(random.uniform(0.2, 0.4))
time.sleep(0.2)
def get_page(page):
print('正在爬取第', page, '页')
try:
url = 'https://shopsearch.taobao.com/search?q=' + quote(KEYWORD)
print(url)
browser.get(url)
if page > 1:
input = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '#shopsearch-pager div.form > input')))
submit = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, '#shopsearch-pager div.form > span.btn.J_Submit')))
slide_down(2.1)
input.clear()
input.send_keys(page)
submit.click()
time.sleep(random.uniform(1, 2))
wait.until(
EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#shopsearch-pager li.item.active > span'), str(page)))
slide_down(2.1)
# wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#list-container .list-item .item-bottom')))
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#list-container .list-item .list-info .info-sum'),'件宝贝'))
time.sleep(random.uniform(1, 2))
get_shops()
except TimeoutException:
print('遇到验证码,需要休息下!')
time.sleep(15)
get_page(page)
def get_shops():
html = browser.page_source
doc = pq(html)
items = doc('#list-container .list-item').items()
for item in items:
shop = {
'shoptitle': item.find('h4 a').text(), #店铺名称
'shopimg': item.find('.list-img a img').attr('src'), #店铺图片
'seller': item.find('.shop-info-list a').text(), #卖家名称
'sales': item.find('.info-sale em').text(), #销量
'products': item.find('.info-sum em').text(), #宝贝数量
'goodcomt': item.find('.good-comt').text() #好评率
}
print(shop)
save_to_mongo(shop)
def save_to_mongo(result):
try:
if db[MONGO_COLLECTION].insert(result):
print('存储到MongoDB成功')
except Exception:
print('存储到MongoDB失败')
def main():
for i in range(1, MAX_PAGE + 1):
get_page(i)
time.sleep(random.uniform(1, 2.5))
browser.close()
if __name__ == '__main__':
main()
经测试,这种方法可以至少顺利抓取3个搜索词的结果即300个页面,出现验证码的概率远少于微博登录的方式,而验证通过的概率远高于微博登录的方式。同样的,上一篇采集淘宝商品也可以用这种方式,抓取效率更高。
这篇文章设置了付费阅读,主要是测试下微信公众号付费阅读功能。当然,不付费也不影响获取主要内容,只是隐藏了回复关键词获取代码这部分。
PS:如果想获得这份代码,关注公众号【Python加SEO做增长】后台回复关键词【淘宝店铺】即可获得这份代码。