文章目錄
一、目的分析
1、京東搜索筆記本電腦字段,按銷量由高到低排序,該網頁作爲開始url,爬取100頁數據,共計 5 (個) *12(行)*100(頁)= 6000(條)
數據。
2、數據爲各個項目詳情頁中的數據,即下圖中的href,可先爬取所有的href,後續再從各鏈接中爬取所需數據。
二、爬取頁面商品所有詳情頁鏈接
即該href鏈接
出現的問題:京東一頁數據爲30項,但分半加載,即先加載15項,下滑加載後半部分,導致爬取結果僅有15項。
解決方法:爬蟲爬取動態網頁,滑動加載項無法爬取問題
1、爬取href鏈接
這裏使用了selenium模塊加載動態網頁
觀察各頁url:
第一頁:https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&psort=3&click=0
第二頁:https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&psort=3&page=3&s=61&click=0
第三頁:https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&psort=3&page=5&s=121&click=0
可以發現Page是1、3、5呈奇數遞增,測試發現後面的page爲偶數時網頁與奇數網頁內容一致,所以我們在循環裏將Url內容改爲'...page={ }'.format((i * 2) - 1)
from selenium import webdriver
from lxml import etree
import time
urls = []
# 使用selenium模擬人爲訪問頁面,獲取數據
def spider_jd(url):
# ChromeOptions() 函數中有谷歌瀏覽器的一些配置
options = webdriver.ChromeOptions()
# 告訴谷歌這裏用的是無頭模式
options.add_argument('headless')
# 創建谷歌瀏覽器對象
driver = webdriver.Chrome('D:\Anaconda3\envs\Python\chromedriver.exe')
# 打開谷歌瀏覽器,進入指定網址的頁面
driver.get(url)
# 模擬下拉頁面動作,是動態頁面加載
driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")
# 停頓2.5秒等待頁面加載完畢!!!(必須留有頁面加載的時間,否則部分瀏覽器獲得的源代碼會不完整。)
time.sleep(2.5)
# 相當於 request.get(url, headers=header)
source = driver.page_source
# 構造了一個XPath解析對象並對HTML文本進行自動修正。
html1 = etree.HTML(source)
# 提取href
href = html1.xpath('//div[@class="p-img"]/a/@href')
# 僅保存前60個值,k值每次循環自增60
for hr in href:
urls.append(hr)
del urls[k:]
driver.close() # 爬取完畢關閉瀏覽器
k = 60
for i in range(1, 100):
url = 'https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&psort=3&page={}&s=61&click=0'.format(
(i * 2) - 1)
spider_jd(url)
k = k + 60
print(urls)
print('爬取完畢關閉瀏覽器')
爬取到的鏈接大部分爲非https:
開頭,所以我們需要在沒有https:的一項前面添加https:
:
for hr in href:
if hr[:6] != 'https:': # 判斷是否爲https:開頭項,爲否則添加https:頭
urls.append('https:' + hr)
urls.append(hr) # https:開頭則直接加入列表
del urls[k:]
爬取所有鏈接完成。
2.將數據存入數據庫
import pymysql
# 鏈接數據庫
def create():
try:
db = pymysql.connect(host = "x.x.x.x", user = "root", password = "***", database = "SPIDER_URL", charset="utf8") # 連接數據庫
# 使用cursor()方法獲取操作遊標
cursor = db.cursor()
# 使用execute方法執行SQL語句
cursor.execute("DROP TABLE IF EXISTS URL")
sql = 'CREATE TABLE URL(url CHAR(50));'
# 執行SQL語句
cursor.execute(sql)
print("連接服務器成功!")
# 關閉光標對象
cursor.close()
# 關閉數據庫連接
db.close()
except:
print("連接服務器失敗!")
# 插入數據
def insert(value):
db = pymysql.connect(host = "x.x.x.x", user = "root", password = "***", database = "SPIDER_URL", charset="utf8")
cursor = db.cursor()
sql = "INSERT INTO URL(url) VALUES (%s)"
try:
cursor.execute(sql, value)
db.commit()
print('插入數據成功!')
except:
db.rollback()
print("插入數據失敗!")
db.close()
完整代碼:
爬蟲爬取京東商品各詳情頁Url並插入mysql數據庫代碼
(爲確保安全,mysql.connect內容需自行編輯)
(mysql需先建立相關庫和表)
(需要配置webdriver,方法鏈接:selenium + cromedriver配置方法)
from selenium import webdriver
from lxml import etree
import time
import pymysql
start = time.perf_counter()
urls = []
# 使用selenium模擬人爲訪問頁面,獲取數據
def spider_jd(url):
# ChromeOptions() 函數中有谷歌瀏覽器的一些配置
options = webdriver.ChromeOptions()
# 告訴谷歌這裏用的是無頭模式
options.add_argument('headless')
# 創建谷歌瀏覽器對象
driver = webdriver.Chrome('D:\Anaconda3\envs\Python\chromedriver.exe')
# 打開谷歌瀏覽器,進入指定網址的頁面
driver.get(url)
# 模擬下拉頁面動作,是動態頁面加載
driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")
# 停頓2.5秒等待頁面加載完畢!!!(必須留有頁面加載的時間,否則部分瀏覽器獲得的源代碼會不完整。)
time.sleep(2.5)
# 相當於 request.get(url, headers=header)
source = driver.page_source
# 構造了一個XPath解析對象並對HTML文本進行自動修正。
html1 = etree.HTML(source)
# 提取href
href = html1.xpath('//div[@class="p-img"]/a/@href')
# 僅保存前60個值,k值每次循環自增60
for hr in href:
if hr[:6] != 'https:' or hr[:6] != 'http:': # 判斷是否爲https:開頭項,爲否則添加https:頭
urls.append('https:' + hr)
else:
urls.append(hr)
del urls[k:]
driver.close() # 爬取完畢關閉瀏覽器
def create():
try:
db = pymysql.connect(host = "x.x.x.x", user = "root", password = "***", database = "SPIDER_URL", charset="utf8") # 連接數據庫
# 使用cursor()方法獲取操作遊標
cursor = db.cursor()
# 使用execute方法執行SQL語句
cursor.execute("DROP TABLE IF EXISTS URL")
sql = 'CREATE TABLE URL(url CHAR(50));'
# 執行SQL語句
cursor.execute(sql)
print("連接服務器成功!")
# 關閉光標對象
cursor.close()
# 關閉數據庫連接
db.close()
except:
print("連接服務器失敗!")
def insert(value):
db = pymysql.connect(host = "x.x.x.x", user = "root", password = "***", database = "SPIDER_URL", charset="utf8")
cursor = db.cursor()
sql = "INSERT INTO URL(url) VALUES (%s)"
try:
cursor.execute(sql, value)
db.commit()
print('插入數據成功!')
except:
db.rollback()
print("插入數據失敗!")
db.close()
k = 60
for i in range(1, 2):
url = 'https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&suggest=1.his.0.0&psort=3&page={}&s=61&click=0'.format(
(i * 2) - 1)
spider_jd(url)
k = k + 60
print(urls)
print('共爬取{}條數據,爬取完畢關閉瀏覽器'.format(len(urls)))
try:
print("正在連接數據庫。。。")
create()
print("正在插入數據。。。")
for url1 in urls:
insert(url1)
except BaseException as e:
print(e)
end = time.perf_counter()
print("項目完成,耗時{}s".format(end-start))
range(1,101),即爬取100頁(6000件商品)時,並優化文字顯示後,結果展示:
數據庫內容