前言
前面介紹了使用selenium和chromedriver通過模擬瀏覽器運(yùn)行的方式可以做到在瀏覽器中看到是什么樣浮梢,抓取的源碼就是什么樣。不用再去管網(wǎng)頁內(nèi)部的JavaScript是如何渲染頁面彤路,也不用管網(wǎng)頁后臺的Ajax接口有哪些參數(shù)秕硝,甚至是加密規(guī)律等。這篇博客是實(shí)戰(zhàn)演練洲尊,通過Selenium爬取淘寶網(wǎng)商品的圖片远豺,名稱,價格坞嘀,購買人數(shù)躯护,店鋪名稱,店鋪所在地信息丽涩,將結(jié)果保存至Mongodb數(shù)據(jù)庫中棺滞。
Chromedriver for linux
上一篇博客只介紹了chromedriver在windows下的安裝
對應(yīng)版本的下載和測試安裝是方法是一樣的
//解壓
unzip chromedriver_linux64.zip
//移動到環(huán)境變量所在的目錄
sudo mv chromedriver /usr/bin
//或者將chromedriver所在目錄,添加到環(huán)境變量
export PATH="$PATH:所在目錄"
//執(zhí)行新的配置
source ~/.porfile
分析一波
1.ajax請求分析
_ksTS,rn這兩個參數(shù)很難發(fā)現(xiàn)其規(guī)律内狸,所以這里不采用構(gòu)造Ajax請求的方式來爬取內(nèi)容检眯,而通過selemium價格網(wǎng)頁最終呈現(xiàn)效果的HTML代碼全部爬取下來,再來提取所要信息
2.商品分析
需要說明的是src 和data-src都是商品圖片的網(wǎng)絡(luò)地址,區(qū)別是前者是縮略圖而后者是高清大圖昆淡,兩者都可以任意爬取锰瘸,這里爬取的是后者
3.頁碼分析
這里不點(diǎn)擊下一頁,而是通過自動輸入頁面數(shù)來進(jìn)行頁面跳轉(zhuǎn)昂灵,一方面是要實(shí)時監(jiān)控爬取到多少頁避凝,另一方面,當(dāng)程序出現(xiàn)異常眨补,下一次運(yùn)行又從第一頁開始管削,下一頁依次爬取,數(shù)據(jù)庫中撑螺,會有重復(fù)記錄
code
1. 獲取商品列表
import pymongo
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
driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)
KEYWORD = 'iMac'
def index_page(page):
print('正在爬取第',page,'頁')
try:
url = 'https://s.taobao.com/search?q='+quote(KEYWORD)
driver.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.presence_of_element_located((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)
通過構(gòu)造查詢參數(shù)含思,得到淘寶網(wǎng)的搜索URLhttps://s.taobao.com/search?q=iMac,q后面接你要搜索的關(guān)鍵詞。就能夠跳轉(zhuǎn)到搜索指定商品后的頁面,也是程序的入口URL
通過改變EYWORD的值含潘,就能爬取不同商品信息;拼接URL的時候用到quote方法饲做,屏蔽特殊字符串,如空格等遏弱,URL地址里是不含空格的盆均,同時將字符串轉(zhuǎn)換為URL編碼格式,以保證URL的正確性漱逸。
下面代碼等待加載時泪姨,使用了WebDriverWait對象,指定等待條件和10s的最長等待時間饰抒,如果在這個時間內(nèi)頁面元素成功加載出來了肮砾,就相應(yīng)結(jié)果并繼續(xù)向下執(zhí)行,否則拋出超時異常袋坑。EC.presence_of_element_located是元素成功加載出來唇敞,EC.presence_of_element_located 意思是元素可以點(diǎn)擊,因?yàn)樗且粋€按鈕咒彤,這個按鈕的作用是選定頁碼后的點(diǎn)擊確定后跳轉(zhuǎn)。
為了驗(yàn)證跳轉(zhuǎn)到了對應(yīng)的頁碼咒精,需要判斷當(dāng)前高亮的頁碼數(shù)是當(dāng)前的頁碼數(shù)(當(dāng)前所在頁碼會高亮顯示,也就是說當(dāng)前頁碼的css是特殊的)镶柱,所以這里使用了另一個等待條件text_to_be_present_in_element,它會等待指定的文本出現(xiàn)在某一個節(jié)點(diǎn)里面時即返回成功模叙。這里我們將高亮的頁碼節(jié)點(diǎn)對應(yīng)的CSS選擇器和當(dāng)前要跳轉(zhuǎn)的頁碼通過參數(shù)傳遞給這個等待條件歇拆,這樣它就會檢測當(dāng)前高亮的頁碼節(jié)點(diǎn)是不是我們傳過來的頁碼數(shù),如果是范咨,就證明頁面成功跳轉(zhuǎn)到了這一頁故觅,頁面跳轉(zhuǎn)成功。
這樣剛才實(shí)現(xiàn)的index_page()方法就可以傳入對應(yīng)的頁碼渠啊,待加載出對應(yīng)頁碼的商品列表后输吏,再去調(diào)用get_products()方法進(jìn)行頁面解析。
這些等待條件的參數(shù)都是特定的css選擇器替蛉,不做贅述了贯溅,圖片已經(jīng)標(biāo)注的很清楚了
2.解析商品列表
def get_products():
html = driver.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)
print('\n')
通過driver.page_source 獲得了不同頁碼下完整html源碼;同時使用Pyqurey來解析網(wǎng)頁,通過已經(jīng)查找的標(biāo)簽躲查,查找這個標(biāo)簽下的子標(biāo)簽或者父標(biāo)簽它浅,而不用從頭開始查找,效率更高;通過find(css).屬性方法,獲取圖片URL,和其他文本信息并構(gòu)造成Json字符串镣煮,調(diào)用save_to_mongo函數(shù)存入數(shù)據(jù)庫中姐霍。
3.將結(jié)果保存到Mogodb中
def save_to_mongo(result):
client = pymongo.MongoClient('mongodb://admin:admin123@localhost:27017/')
db = client['taobao']
collection = db['products']
try:
if collection.insert(result):
print("成功保存到MongoDB")
except Exception:
print('someing wrong with MongDB')
python3通過認(rèn)證方式連接Mongodb數(shù)據(jù)庫,admin是我的用戶名,admin123是我的密碼镊折,接著指定數(shù)據(jù)庫和集合胯府,調(diào)用insert方法插入數(shù)據(jù)。
4.定義爬取頁數(shù)
def main():
MAX_PAGE = 100
for i in range(1,MAX_PAGE+1):
index_page(i)
driver.close()
if __name__ =='__main__':
main()
簡單for循環(huán)腌乡,并通過range生成1到100的數(shù)傳遞給index_page函數(shù)盟劫。
5.完整代碼
import pymongo
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
driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)
KEYWORD = 'iMac'
def index_page(page):
print('正在爬取第',page,'頁')
try:
url = 'https://s.taobao.com/search?q='+quote(KEYWORD)
driver.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 = driver.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)
print('\n')
def save_to_mongo(result):
client = pymongo.MongoClient('mongodb://admin:admin123@localhost:27017/')
db = client['taobao']
collection = db['products']
try:
if collection.insert(result):
print("成功保存到MongoDB")
except Exception:
print('someing wrong with MongDB')
MAX_PAGE = 100
def main():
for i in range(1,MAX_PAGE+1):
index_page(i)
driver.close()
if __name__ =='__main__':
main()
小結(jié)
這段程序是對以前所學(xué)知識的綜合利用,Mongodb是前幾天現(xiàn)學(xué)現(xiàn)用与纽,這是我第一次使用侣签,關(guān)系型數(shù)據(jù)庫Oracle,Sql server,Mysql都用過,基本知識也有掌握急迂,非關(guān)系型數(shù)據(jù)庫
Mongodb以后可能會寫幾篇學(xué)習(xí)筆記