利用Python爬取京東商品信息, 實現可見即可爬
以爬取Macbook商品信息爲例,通過Selenium實現可見即可爬的功能
關於Selenium的driver配置問題https://blog.csdn.net/qq_19381989/article/details/95893317
一,分析頁面
1. 分析搜索方式
簡化一下就是:https://search.jd.com/Search?keyword=MacBook
可知可以根據URL中的keyword實現搜索,查詢
2. 分析商品元素
可見每個商品都在class爲gl-warp clearfix的ul下的li下,商品的信息都在其中的div中,這就好辦了,re,xpath,pyquery都可以得到商品的信息了。
3. 分析如何進行翻頁
由URL可知是由page控制且每增加兩位翻一頁
https://search.jd.com/Search?keyword=MacBook&page=3
二,代碼實現
1. 引用的包,全局變量...:
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 multiprocessing.pool import Pool
from urllib.parse import quote
from pyquery import PyQuery as pq
import pymongo
import time
options = webdriver.ChromeOptions()
options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=options)
wait = WebDriverWait(browser,10)
KEYWORD = 'macbook'
MONGO_DB = 'jd'
MONGO_COLLECTION = 'products'
client = pymongo.MongoClient('mongodb://admin:1234qwer@localhost:27017')
db = client[MONGO_DB]
headers = {
'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'x-requested-with':'XMLHttpRequest'#分析頁面的時候看到有ajax解析,應該是用於翻頁的
}
因爲最後需要將數據存儲在mongodb中,故需要引用pymongo,搜索的關鍵詞由KEYWORD來控制。
學習時一定要摸清楚selenium的顯式等待和隱式等待,selenium其實就是模仿人類去點擊網頁,這中間js渲染網頁,需要一些時間,如果不做相應的處理會浪費大量的時間,從而影響爬蟲效率,我這裏只是定義了一個簡單的隱式等待。
其中加入的參數 '--headless' 可以實現隱藏web窗口的功能
2. 搜索爬取塊:
def index_page(page):
'''
抓取索引頁
:param page: 頁碼
:return: 網頁源碼
'''
print('正在爬取第', page, '頁')
try:
url = 'https://search.jd.com/Search?keyword={}&enc=utf-8&page={}'.format(quote(KEYWORD),page*2-1)
print(url)
browser.get(url)
time.sleep(2)
return browser.page_source
# browser.close()
except TimeoutException:
index_page(page)
由page控制翻頁,page*2-1即可實現一頁一頁的爬取,爬取成功時返回網頁源代碼,不成功時重新爬取該頁信息
3. 提取商品信息塊:
通過css定位,Google,搜狐都會有右鍵定位的功能,可以結合他們提供的位置然後再進一步優化
def get_products(html):
'''
提取商品信息
:param html: 網頁源碼
:return:
'''
# html = browser.page_source
doc = pq(html)
items = doc('#J_goodsList > ul > li').items()#因爲全部都在ul下的li中
for item in items:
product = {
'image': item.find('div > div.p-img > a > img').attr('src'),#J_goodsList > ul > li:nth-child(1) > div > div.p-img > a > img
'price': item.find('div > div.p-price > strong > i').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-price > strong > i
'talk': item.find('div > div.p-commit > strong > a').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-commit > strong > a
'title': item.find('div > div.p-name.p-name-type-2 > a > em').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-name.p-name-type-2 > a > em
'shop': item.find('div.p-shop > span > a').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-shop > span > a
'href': item.find('div > div.p-img > a').attr('href'),#J_goodsList > ul > li:nth-child(1) > div > div.p-img > a
}
print(product)
save_to_mongodb(product)#保存到mongodb
def save_to_mongodb(product):
try:
if db[MONGO_COLLECTION].insert(product):
print('Save_Successful!!!')#保存成功!
except Exception:
print('Error save OR Done')
利用pyquery定位可以提高定位的速度,定位成功後再由存儲模塊保存
整合代碼
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 multiprocessing.pool import Pool
from urllib.parse import quote
from pyquery import PyQuery as pq
import pymongo
import time
import csv
options = webdriver.ChromeOptions()
options.add_argument('--headless')
browser = webdriver.Chrome(chrome_options=options)
wait = WebDriverWait(browser,10)
KEYWORD = 'macbook'
MONGO_DB = 'jd'
MONGO_COLLECTION = 'products'
client = pymongo.MongoClient('mongodb://admin:1234qwer@localhost:27017')
db = client[MONGO_DB]
headers = {
'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
'x-requested-with':'XMLHttpRequest'
}
def index_page(page):
'''
抓取索引頁
:param page: 頁碼
:return: 網頁源碼
'''
print('正在爬取第', page, '頁')
try:
url = 'https://search.jd.com/Search?keyword={}&enc=utf-8&page={}'.format(quote(KEYWORD),page*2-1)
print(url)
browser.get(url)
time.sleep(2)
return browser.page_source
# browser.close()
except TimeoutException:
index_page(page)
def get_products(html):
'''
提取商品信息
:param html: 網頁源碼
:return:
'''
# html = browser.page_source
doc = pq(html)
items = doc('#J_goodsList > ul > li').items()
# print(items)
for item in items:
# print(item)
product = {
'image': item.find('div > div.p-img > a > img').attr('src'),#J_goodsList > ul > li:nth-child(1) > div > div.p-img > a > img
'price': item.find('div > div.p-price > strong > i').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-price > strong > i
'talk': item.find('div > div.p-commit > strong > a').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-commit > strong > a
'title': item.find('div > div.p-name.p-name-type-2 > a > em').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-name.p-name-type-2 > a > em
'shop': item.find('div.p-shop > span > a').text(),#J_goodsList > ul > li:nth-child(1) > div > div.p-shop > span > a
# 'href': re.findall('href="(.*?)"',item.find('div > div.p-img > a').html())#J_goodsList > ul > li:nth-child(11) > div > div.p-img > a #J_goodsList > ul > li:nth-child(22) > div > div.p-img > a
'href': item.find('div > div.p-img > a').attr('href'),#J_goodsList > ul > li:nth-child(1) > div > div.p-img > a
}
print(product)
save_to_mongodb(product)
def save_to_mongodb(product):
try:
if db[MONGO_COLLECTION].insert(product):
print('Save_Successful!!!')
except Exception:
print('Error save OR Done')
if __name__ == '__main__':
# pool = Pool()
# group = [i for i in range(1,78)]
# print(group)
# pool.map(main, group)
# pool.close()
# pool.join()
for i in range(1,78):#一共77頁
get_products(index_page(i))
這樣子就實現了selenium的可見可爬的功能了
也可以通過搭建pool池,實現多進程爬取網頁,提高爬取速度
三,運行