雖然淘寶的頁面數(shù)據(jù)是通過 Ajax 獲取的晤碘,也就是可以通過開發(fā)者模式直接找到它請求數(shù)據(jù)的接口吞杭,并且發(fā)現(xiàn)返回的數(shù)據(jù)是 json 的格式笛辟;但是這里需要注意的是這些 Ajax 接口的參數(shù)比較復(fù)雜已艰,包含了加密密鑰逞盆,因此如果想自己構(gòu)造 Ajax 參數(shù)是比較困難的券勺。
既然那么困難搞到數(shù)據(jù)绪钥,那么有沒有辦法使抓取的成本第一點(diǎn)呢?當(dāng)然有关炼,一種是使用 特定的數(shù)據(jù)接口 程腹;另一種就是使用 selenium了,selenium 有個(gè)特點(diǎn)就是 可見即所得儒拂。
那么接下來我們開始觀察頁面效果圖:
image.png
經(jīng)過效果圖的觀察跪楞,我們不難發(fā)現(xiàn)規(guī)律:我們要加載商品列表的節(jié)點(diǎn)缀去;頁面跳轉(zhuǎn)時(shí)通過頁面輸入框再點(diǎn)擊“確定”按鈕進(jìn)行跳轉(zhuǎn),并且只需判斷當(dāng)前高亮的頁碼數(shù)是當(dāng)前的頁碼數(shù)即可甸祭。
一缕碎、首先導(dǎo)入相應(yīng)的模塊:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from urllib.parse import quote
from pyquery import PyQuery as pq
二、加載及跳轉(zhuǎn)邏輯的代碼函數(shù)如下:
browser = webdriver.Chrome() # 瀏覽器對象
wait = WebDriverWait(browser, 10) # 加載等待最大時(shí)間
KEYWORD = "華為榮耀10"
def index_page(page):
print("正在抓取第 ", page, "頁...")
try:
url = r'https://s.taobao.com/search?q='+ quote(KEYWORD)
browser.get(url)
if page > 1: # 當(dāng)頁碼大于 1 的時(shí)候則進(jìn)行跳轉(zhuǎn)
# 節(jié)點(diǎn)加載出來池户,傳入定位元組咏雌,如(By.ID, 'p')
input_word = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager div.form > input'))) # 輸入頁碼框
# 節(jié)點(diǎn)可點(diǎn)擊
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager div.form > span.btn.J_Submit'))) # 頁碼跳轉(zhuǎn)"確定"按鈕
input_word.clear() # 清空編輯框
input_word.send_keys(page) # 將頁碼填充到輸入框
submit.click() # 點(diǎn)擊"確定"按鈕
# 某個(gè)節(jié)點(diǎn)文本包含某文字
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager li.item.active > span'), str(page))) # 翻頁按鈕列表選項(xiàng)數(shù)字
# 節(jié)點(diǎn)加載出來,傳入定位元組校焦,如(By.ID, 'p')
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.m-itemlist .items .item'))) # 渲染商品所在列表選項(xiàng)
# 解析數(shù)據(jù)
get_products()
except TimeoutException as e:
index_page(page)
到這里赊抖,你可以直接運(yùn)行該函數(shù)看是否能成功加載源碼,這里我不做演示寨典;那么接下來在觀察我們所要加載信息(商品圖片氛雪、名稱、價(jià)格耸成、購買人數(shù)报亩、店鋪名稱、店鋪地址)的頁面節(jié)點(diǎn):
image.png
三井氢、觀察商品節(jié)點(diǎn)之后解析代碼如下(由于截圖大小有限弦追,其它標(biāo)簽自行觀察):
# 解析函數(shù)-提取商品信息
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)
四、編寫主函數(shù)并調(diào)用:
def main():
#page = 1 # 據(jù)觀察總共有 100 頁
for page in range(1, 11):
index_page(page)
if __name__ == '__main__':
main()
運(yùn)行部分效果圖如下:
image.png
如果我們不想爬取的時(shí)候有瀏覽器彈出花竞,那么有兩種方式可以做到:1- 使用 Chrome Headless 模式 (這個(gè)模式前面一章有介紹并使用過)劲件;2- 對接 PhantomJS
五、首先看第一種 -> 直接將 webdriver 的聲明修改為:
#browser = webdriver.Chrome() # 瀏覽器對象
chrome_options = webdriver.ChromeOptions() # 獲取 ChromeOptions 對象
chrome_options.add_argument('--headless') # 添加 headless 參數(shù)
browser = webdriver.Chrome(chrome_options=chrome_options) # 初始化 Chrome 對象
六约急、第二種 -> 同理零远,直接將 webdriver 的聲明修改為:
path = r"E:\\KaiFaSoftware\\MyPython\\MyPhantomjs\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe"
# browser = webdriver.PhantomJS(executable_path=path)
# 我們還可以通過命令行配置,設(shè)置緩存和禁用圖片加載功能厌蔽,進(jìn)一步提高爬取效率
SERVICE_ARGS = ['--load-images=false','--disk-cache=true']
browser = webdriver.PhantomJS(executable_path=path,service_args=SERVICE_ARGS)
這里值得注意的是:如果配置了環(huán)境變量則不需要 path 指定路徑了牵辣,還有提供一個(gè) PhantomJS 的下載地址 -> http://phantomjs.org/download.html
最后的話非常感謝崔老師的思路,嘿嘿躺枕,相信通過本次實(shí)戰(zhàn)同學(xué)們應(yīng)該學(xué)到了不少了服猪;本次實(shí)戰(zhàn)到此為止供填,感恩一切拐云。。近她。 *^_^*