Selenium+BeautifulSoup實現懶加載頁面數據抓取

背景描述:

1.爬取列表頁數據

2.頁面數據時動態懶加載,只有當頁面滾動才能加載出相關圖片

3.查看頁面源碼所得結構和頁面顯示的結構不一樣

4.頁面滾動到底部,中間部分的圖片無法獲取到

BeautifulSoup適合與爬取靜態頁面數據,擅長解析頁面結構,獲取元素信息

Selenium適合於模擬手動打開瀏覽器,適合處理懶加載的數據加載,可以定製交互式操作,用於自動化測試

需要先安裝Chromedriver,安裝過程:

查看chrome瀏覽器版本:

 在https://registry.npmmirror.com/binary.html?path=chromedriver/搜索相近版本,下載

下載chromedriver_win32.zip即可,解壓後將路徑配置到windows環境變量的Path裏面,接下來就可以通過from selenium import webdriver 使用模擬瀏覽器。

解決方案:

目前一般使用BeautifulSoup可以實現簡單動態頁面的數據抓取,考慮到時懶加載,需要考慮結合頁面實際情況應用。

經分析,頁面數據爲懶加載,通過javascript 動態替換數據,實現頁面實時的渲染,我們選擇Selenium+BeautifulSoup實現。

因爲列表頁上產品比較多,需要鼠標下拉才能實現動態加載圖片,所以需要使用Selenium,並且安裝webdriver的chrome模擬用戶行爲。

抓取數據的網站:https://www.firstbottlewines.com/wines

代碼:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
import csv
import codecs

# 通過指定chromedriver的路徑來實例化driver對象,chromedriver放在當前目錄。
# chromedriver已經添加環境變量
options= Options()
options.add_experimental_option("detach", True)
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
 
# 控制瀏覽器訪問url地址
driver.get("https://www.firstbottlewines.com/wines")
 
# 實現滾輪向下滑動,第一個參數是橫向滾輪,第二個參數是縱向
page_height=driver.execute_script("return document.body.scrollHeight;")
for i in range(1,31):
    scroll_s=str((i-1)*page_height/30)
    scroll_e=str(i*page_height/30)
    js = 'window.scrollTo('+scroll_s + ','+scroll_e+')'
    # 執行js代碼
    driver.execute_script(js)
    time.sleep(4)

# Since you are calling BeautifulSoup as soup
soup_page = BeautifulSoup(driver.page_source, 'html.parser')
info_doms = soup_page.find_all('div',attrs={'filter-product mb-1 col-sm-6 col-md-3'})
params = []
i=1
for dom in info_doms:
    print(dom)
    #brand
    brand = dom.find('h3',class_='product-title').text
    brand_fomart=str(brand).strip().replace('\n', '').replace('\r', '').replace('\t', '')
    print('brand',brand_fomart)
    #type
    type_str=str(dom.find('div',class_='product-specs').text).strip().replace('\n', '').replace('\r', '').replace(u'\xa0', u' ')
    type = type_str.split('|')[0].strip()
    print('type',type)
    #year
    year = str(brand_fomart)[-4:].strip()
    print('year',year)
    #origin
    origin = type_str.split('|')[1].strip()
    print('origin',origin)
    #price
    price = str(dom.find('span',class_='product-actual-price').text).strip()
    print('price',price)
    #image_url
    img=dom.findAll('img')
    #image_url = dom.find('img',class_='mb-0 v-lazy-image v-lazy-image-loaded').get("src")
    image_url =str(img[0]["src"]).strip()
    print('image_url',image_url)
    res = [str(i),brand_fomart,type,year,origin,price,image_url]
    #res = brand_fomart+','+type+','+year+','+origin+','+price+','+image_url+ '\n'
    params.append(res)
    i=i+1
    #print(params)
with open('text.txt', 'w') as f:
    #for dom in wq1:
        #f.write(dom.get_text().strip())
        f.write(str(params)) 

#with open('red_wine.csv', 'w',encoding="utf-8",newline="") as f:
with open('red_wine.csv', 'w',encoding="utf-8-sig",newline="") as f:
    #f.write("Text;Time\n")
    #f.write(codecs.BOM_UTF8)
    wr = csv.writer(f,delimiter=',', quoting=csv.QUOTE_ALL)
    #wr.writerow(['Text', 'Time'])
    #for i in [params]:
        #wr.writerows(i)
    for p in params:
            f.write(p[0]+'|'+p[1]+'|'+p[2]+'|'+p[3]+'|'+p[4]+'|'+p[5]+'|'+p[6]+'\n')


# 退出瀏覽器
driver.quit()
View Code

注:解決寫入csv亂碼,將寫入時的配置改爲 :encoding='utf-8-sig'

效果:

開啓chrome webdriver,自動模擬手動拖動網頁,實現懶加載,獲取真實圖片

csv結果:

 

 導入到postgresql,初始化的表結構:

 使用dbeaver的import date 直接導入數據,

修改分隔符,選擇映射columns,

 選擇進行映射,

 即可完成導入,導入成功。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章