百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

使用Python 爬取京东、淘宝等商品详情页的数据,避开反爬虫机制

itomcoil 2024-12-18 14:54 26 浏览

以下是爬取京东商品详情的Python3代码,以excel存放链接的方式批量爬取。excel如下

代码如下

私信小编01即可获取大量Python学习资源

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压缩包一个一个上传。才成功。

相关推荐

Python 类型注解的进阶应用:从静态检查到元编程

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。如需转载请附上本文源链接!近年来,Python类型注解(TypeHinting)逐渐从一个可选的功能演变为大型...

高阶Python|返回类型提示技巧 (1)

引言Python提供了一种可选的特性——类型提示,它有助于提高代码的可读性、可推理性和可调试性。通过类型提示,开发者能够清楚地了解变量、函数参数和返回值应具备的数据类型。在开发那些需要高度灵活性的应用...

跟我一起学Python-函数的定义(基础)

一.函数的定义和调用1.语法:def函数名():函数封装的代码函数最好能够表达函数内部封装的代码功能,方便后续的调用,函数命名需要遵循规则字母、数字、下划线、不能以数字开头,不能使用系统关键字。&#...

Python函数参数和返回值类型:让你的代码更清晰、更健壮

在Python开发中,你是否遇到过这些抓狂时刻?同事写的函数参数类型全靠猜调试两小时发现传了字符串给数值计算函数重构代码时不知道函数返回的是列表还是字典今天教你两招,彻底解决类型混乱问题!让你的...

python入门到脱坑 函数—参数(python 参数处理)

本文包括必须参数,关键参数,默认参数以及可变参数Python函数参数详解一、位置参数(必需参数)位置参数是函数调用时必须提供的参数,且顺序必须与定义时一致。基本用法defgreet(name,me...

python入门到脱坑经典案例—求两个数的和

下面为大家讲解如何求两个数之和——这是编程中最基础但最重要的算术运算之一。我们会从最简单的情况逐步深入,并穿插相关编程概念。1.最基础版本#定义两个变量num1=5num2=3#...

新手必看!30 个 Python 核心函数详解,手把手教你玩转编程

Python中30个核心函数及其含义、代码示例、注释和应用场景:print():用于输出文本或变量的值到控制台。message="Hello,World!"#定义一个...

Python快速入门教程1:基本语法、数据类型、运算符、数字字符串

Python3的基础教程,涵盖了基本语法、数据类型、类型转换、解释器、注释、运算符、数字和字符串等内容,并附有使用实例场景。Python3的基础教程,涵盖了基本语法、数据类型、类型转换、解释器、注释、...

编程小白学做题:Python 的经典编程题及详解,附代码和注释(八)

适合Python3+的6道编程练习题(附详解)1找出字典中值最小的键题目描述:找出字典中值最小的键(如{"a":5,"b":2,"c...

新手学Python避坑,学习效率狂飙! 二十一、print()函数

感谢大家对《新手学Python避坑,学习效率狂飙!》系列的点赞、关注和收藏,今天这编是这个系列的第二十一个分享,前面还有二十个,大家可以关注下之前发布的文章。下面是我们今天第三个的分享:在Pytho...

编程小白学做题:Python 的经典编程题及详解,附代码和注释(六)

适合Python3+的6道编程练习题(附详解)1、打印杨辉三角的前n行题目描述:给定正整数n,打印杨辉三角的前n行(每个数等于它上方两数之和,每行首尾为1)。编写思路:杨辉三角的第i...

让你的Python代码更易读:7个提升函数可读性的实用技巧

如果你正在阅读这篇文章,很可能你已经用Python编程有一段时间了。今天,让我们聊聊可以提升你编程水平的一件事:编写易读的函数。请想一想:我们花在阅读代码上的时间大约是写代码的10倍。所以,每当你创建...

python入门到脱坑 函数—return语句

Python函数中的return语句详解一、return语句基础1.1基本功能return语句用于从函数中返回一个值,并立即结束函数的执行。defadd(a,b):returna+...

编程小白学做题:Python 的经典编程题及详解,附代码和注释(七)

适合Python3+的6道编程练习题(附详解)1.检查字符串是否以指定子串开头题目描述:判断字符串是否以给定子串开头(如"helloworld"以"hello&...

python的注释符是什么(python的合法注释符号是什么)

python的注释符是什么?python的注释符包括单行注释符和多行注释符。一、python单行注释符号(#)井号(#)常被用作单行注释符号,在代码中使用#时,它右边的任何数据都会被忽略,当做是注释。...