使用Python 爬取 京東 ,淘寶。 商品詳情頁的數據。(避開了反爬蟲機制)


以下是爬取京東商品詳情的Python3代碼,以excel存放鏈接的方式批量爬取。excel如下

 

代碼如下

from selenium import webdriver
from lxml import etree
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import datetime
import calendar
import logging
from logging import handlers
import requests
import os
import time
import pymssql
import openpyxl
import xlrd
import codecs



class EgongYePing:

     options = webdriver.FirefoxOptions()
     fp = webdriver.FirefoxProfile()
     fp.set_preference("browser.download.folderList",2)  
     fp.set_preference("browser.download.manager.showWhenStarting",False)
     fp.set_preference("browser.helperApps.neverAsk.saveToDisk","application/zip,application/octet-stream")
     global driver 
     driver= webdriver.Firefox(firefox_profile=fp,options=options)
     def Init(self,url,code):
                       print(url.strip())
                       driver.get(url.strip())
                       #driver.refresh()
                       # 操作瀏覽器屬於異步,在網絡出現問題的時候。可能代碼先執行。但是請求頁面沒有應答。所以硬等
                       time.sleep(int(3))
                       html = etree.HTML(driver.page_source) 
                       if driver.title!=None:
                         listImg=html.xpath('//*[contains(@class,"spec-list")]//ul//li//img')
                         if len(listImg)==0:
                              pass
                         if len(listImg)>0:
                                            imgSrc=''
                                            for item in range(len(listImg)):    
                                                 imgSrc='https://img14.360buyimg.com/n0/'+listImg[item].attrib["data-url"]
                                                 print('頭圖下載:'+imgSrc)
                                                 try:
                                                  Headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
                                                  r = requests.get(imgSrc, headers=Headers, stream=True)
                                                  if r.status_code == 200:
                                                     imgUrl=''
                                                     if item==0:
                                                          imgUrl+=code + "_主圖_" + str(item)  + '.' + imgSrc.split('//')[1].split('/')[len(imgSrc.split('//')[1].split('/'))-1].split('.')[1]
                                                     else:
                                                          imgUrl+=code + "_附圖_" + str(item)  + '.' + imgSrc.split('//')[1].split('/')[len(imgSrc.split('//')[1].split('/'))-1].split('.')[1]
                                                     open(os.getcwd()+'/img/'+  imgUrl , 'wb').write(r.content) # 將內容寫入圖片
                                                  del r
                                                 except Exception as e:
                                                    print("圖片禁止訪問:"+imgSrc) 
                         listImg=html.xpath('//*[contains(@class,"ssd-module")]') 
                         if len(listImg)==0:
                              listImg=html.xpath('//*[contains(@id,"J-detail-content")]//div//div//p//img')
                         if len(listImg)==0:
                              listImg=html.xpath('//*[contains(@id,"J-detail-content")]//img')
                         if len(listImg)>0:
                               for index in range(len(listImg)):  
                                    detailsHTML=listImg[index].attrib
                                    if 'data-id' in detailsHTML:
                                          try:
                                           details= driver.find_element_by_class_name("animate-"+listImg[index].attrib['data-id']).value_of_css_property('background-image')
                                           details=details.replace('url(' , ' ')
                                           details=details.replace(')' , ' ')
                                           newDetails=details.replace('"', ' ')
                                           details=newDetails.strip()
                                           print("詳情圖下載:"+details)
                                           try:
                                                  Headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
                                                  r = requests.get(details, headers=Headers, stream=True)
                                                  if r.status_code == 200:
                                                     imgUrl=''
                                                     imgUrl+=code + "_詳情圖_" + str(index)  + '.' + details.split('//')[1].split('/')[len(details.split('//')[1].split('/'))-1].split('.')[1]
                                                     open(os.getcwd()+'/img/'+   imgUrl, 'wb').write(r.content) # 將內容寫入圖片
                                                  del r
                                           except Exception as e:
                                                    print("圖片禁止訪問:"+details) 
                                          except Exception as e:      
                                               print('其他格式的圖片不收錄');       
                                    if  'src' in detailsHTML:
                                         try:
                                           details= listImg[index].attrib['src']
                                           if 'http' in details:
                                                     pass
                                           else:
                                                     details='https:'+details
                                           print("詳情圖下載:"+details)
                                           try:
                                                  Headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
                                                  r = requests.get(details, headers=Headers, stream=True)
                                                  if r.status_code == 200:
                                                     imgUrl=''
                                                     imgUrl+=code + "_詳情圖_" + str(index)  + '.' + details.split('//')[1].split('/')[len(details.split('//')[1].split('/'))-1].split('.')[1]
                                                     open(os.getcwd()+'/img/'+   imgUrl, 'wb').write(r.content) # 將內容寫入圖片
                                                  del r
                                           except Exception as e:
                                                    print("圖片禁止訪問:"+details) 
                                         except Exception as e:      
                                               print('其他格式的圖片不收錄'); 

                       print('結束執行')

         

     @staticmethod
     def readxlsx(inputText):
        filename=inputText
        inwb = openpyxl.load_workbook(filename)  # 讀文件
        sheetnames = inwb.get_sheet_names()  # 獲取讀文件中所有的sheet,通過名字的方式
        ws = inwb.get_sheet_by_name(sheetnames[0])  # 獲取第一個sheet內容
        # 獲取sheet的最大行數和列數
        rows = ws.max_row
        cols = ws.max_column
        for r in range(1,rows+1):
            for c in range(1,cols):
                if ws.cell(r,c).value!=None and r!=1 :
                 if 'item.jd.com' in str(ws.cell(r,c+1).value) and str(ws.cell(r,c+1).value).find('i-item.jd.com')==-1:
                     print('支持:'+str(ws.cell(r,c).value)+'|'+str(ws.cell(r,c+1).value))
                     EgongYePing().Init(str(ws.cell(r,c+1).value),str(ws.cell(r,c).value))
                 else:
                     print('當前格式不支持:'+(str(ws.cell(r,c).value)+'|'+str(ws.cell(r,c+1).value)))
                     pass
        pass

if __name__ == "__main__":
                 start = EgongYePing()
                 start.readxlsx(r'C:\Users\newYear\Desktop\爬圖.xlsx')

基本上除了過期的商品無法訪問以外。對於京東的三種頁面結構都做了處理。能訪問到的商品頁面。還做了模擬瀏覽器請求訪問和下載。基本不會被反爬蟲屏蔽下載。

 

 

 上面這一段是以火狐模擬器運行

 

 

 上面這一段是模擬瀏覽器下載。如果不加上這一段。經常會下載幾十張圖片后,很長一段時間無法正常下載圖片。因為沒有請求頭被認為是爬蟲。

 

上面這段是京東的商品詳情頁面,經常會三種?(可能以后會更多的頁面結構)

所以做了三段解析。只要沒有抓到圖片就換一種解析方式。這楊就全了。

 

 京東的圖片基本只存/1.jpg。然后域名是 https://img14.360buyimg.com/n0/。所以目前要拼一下。

 

 

 京東還有個很蛋疼的地方是圖片以data-id拼進div的背景元素里。所以取出來的時候要繞一下。還好也解決了。

 

以下是爬取淘寶商品詳情的Python3代碼,以excel存放鏈接的方式批量爬取。excel如下

 

因為這次是淘寶和京東一起爬取。所以在一個excel里。代碼里區分淘寶和京東的鏈接。以下是代碼

from selenium import webdriver
from lxml import etree
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import datetime
import calendar
import logging
from logging import handlers
import requests
import os
import time
import pymssql
import openpyxl
import xlrd
import codecs



class EgongYePing:

     options = webdriver.FirefoxOptions()
     fp = webdriver.FirefoxProfile()
     fp.set_preference("browser.download.folderList",2)  
     fp.set_preference("browser.download.manager.showWhenStarting",False)
     fp.set_preference("browser.helperApps.neverAsk.saveToDisk","application/zip,application/octet-stream")
     global driver 
     driver= webdriver.Firefox(firefox_profile=fp,options=options)
     def Init(self,url,code):
                       #driver = webdriver.Chrome('D:\python3\Scripts\chromedriver.exe')
                       #driver.get(url)
                       print(url.strip())
                       driver.get(url.strip())
                       #driver.refresh()
                       # 操作瀏覽器屬於異步,在網絡出現問題的時候。可能代碼先執行。但是請求頁面沒有應答。所以硬等
                       time.sleep(int(3))
                       html = etree.HTML(driver.page_source) 
                       if driver.title!=None:
                         listImg=html.xpath('//*[contains(@id,"J_UlThumb")]//img')
                         if len(listImg)==0:
                              pass
                         if len(listImg)>0:
                                            imgSrc=''
                                            for item in range(len(listImg)):    
                                                 search=listImg[item].attrib
                                                 if 'data-src' in search:
                                                    imgSrc=listImg[item].attrib["data-src"].replace('.jpg_50x50','')
                                                 else:
                                                    imgSrc=listImg[item].attrib["src"]
                                                 if 'http' in imgSrc:
                                                     pass
                                                 else:
                                                     imgSrc='https:'+imgSrc
                                                 print('頭圖下載:'+imgSrc)
                                                 try:
                                                  Headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
                                                  r = requests.get(imgSrc, headers=Headers, stream=True)
                                                  if r.status_code == 200:
                                                     imgUrl=''
                                                     if item==0:
                                                          imgUrl+=code + "_主圖_" + str(item)  + '.' + imgSrc.split('//')[1].split('/')[len(imgSrc.split('//')[1].split('/'))-1].split('.')[1]
                                                     else:
                                                          imgUrl+=code + "_附圖_" + str(item)  + '.' + imgSrc.split('//')[1].split('/')[len(imgSrc.split('//')[1].split('/'))-1].split('.')[1]
                                                     open(os.getcwd()+'/img/'+  imgUrl , 'wb').write(r.content) # 將內容寫入圖片
                                                  del r
                                                 except Exception as e:
                                                    print("圖片禁止訪問:"+imgSrc) 
                         listImg=html.xpath('//*[contains(@id,"J_DivItemDesc")]//img')
                         if len(listImg)>0:
                               for index in range(len(listImg)):  
                                    detailsHTML=listImg[index].attrib
                                    if 'data-ks-lazyload' in detailsHTML:
                                        details= listImg[index].attrib["data-ks-lazyload"]
                                        print("詳情圖下載:"+details)
                                    else:
                                        details= listImg[index].attrib["src"]
                                        print("詳情圖下載:"+details)
                                    try:
                                                  Headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0'}
                                                  r = requests.get(details, headers=Headers, stream=True)
                                                  if r.status_code == 200:
                                                     imgUrl=''
                                                     details=details.split('?')[0]
                                                     imgUrl+=code + "_詳情圖_" + str(index)  + '.' + details.split('//')[1].split('/')[len(details.split('//')[1].split('/'))-1].split('.')[1]
                                                     open(os.getcwd()+'/img/'+   imgUrl, 'wb').write(r.content) # 將內容寫入圖片
                                                  del r
                                    except Exception as e:
                                                    print("圖片禁止訪問:"+details)  
                       print('結束執行')

         

     @staticmethod
     def readxlsx(inputText):
        filename=inputText
        inwb = openpyxl.load_workbook(filename)  # 讀文件
        sheetnames = inwb.get_sheet_names()  # 獲取讀文件中所有的sheet,通過名字的方式
        ws = inwb.get_sheet_by_name(sheetnames[0])  # 獲取第一個sheet內容
        # 獲取sheet的最大行數和列數
        rows = ws.max_row
        cols = ws.max_column
        for r in range(1,rows+1):
            for c in range(1,cols):
                if ws.cell(r,c).value!=None and r!=1 :
                 if 'item.taobao.com' in str(ws.cell(r,c+1).value):
                     print('支持:'+str(ws.cell(r,c).value)+'|'+str(ws.cell(r,c+1).value))
                     EgongYePing().Init(str(ws.cell(r,c+1).value),str(ws.cell(r,c).value))
                 else:
                     print('當前格式不支持:'+(str(ws.cell(r,c).value)+'|'+str(ws.cell(r,c+1).value)))
                     pass
        pass

if __name__ == "__main__":
                 start = EgongYePing()
                 start.readxlsx(r'C:\Users\newYear\Desktop\爬圖.xlsx')

 

淘寶有兩個問題,一個是需要綁定賬號登錄訪問。這里是代碼斷點。然后手動走過授權。

 

 

 

 

 第二個是被休息和懶惰加載。被休息。其實沒影響的。一個頁面結構已經加載出來了。然后也不會影響訪問其他的頁面。

 

 

 至於懶惰加載嘛。對我們也沒啥影響。如果不是直接寫在src里那就在判斷一次取 data-ks-lazyload就出來了。

 

 最后就是爬取的片段截圖

 

 建議還是直接將爬取的數據存服務器,數據庫,或者圖片服務器。因為程序挺靠譜的。一萬條數據。爬了26個G的文件。最后上傳的時候差點累死了

 

 是真的大。最后還要拆包。十幾個2g壓縮包一個一個上傳。才成功。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM