使用Selenium+chrome+scrapy完成京东商品信息爬取

一,准备工作

1.安装Selenium库 

Selenium通过使用 WebDriver 支持市场上所有主流浏览器的自动化。 Webdriver 是一个 API 和协议,它定义了一个语言中立的接口,用于控制 web 浏览器的行为。 每个浏览器都有一个特定的 WebDriver 实现,称为驱动程序。 驱动程序是负责委派给浏览器的组件,并处理与 Selenium 和浏览器之间的通信。

如果使用的是Pycharm软件,则可以直接Python解释器中直接添加,如果无法添加则可通过命令添加:打开DOS命令窗口输入:

pip install selenium

如再次无法安装则用国内镜像资源网站添加:

pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple

成功后重启Pycharm,软件会自动扫描本机原装的库。

2.安装scrapy库

步骤与安装Selenium一样,直接放代码:

pip install scrapy
pip install scrapy-i https://pypi.tuna.tsinghua.edu.cn/simple

3.Chorme浏览器安装

由于需要用Chorme浏览器启动,要求Chorme版本和ChormeDriver版本严格一致,故在安装chorme和chormedriver的时候一定要版本一致,我直接把下载网站(99.0.4844.51版本)放在下面,选择有相同版本的chorme和chormedriver进行下载:

Chorme

Chorme浏览器(99.0.4844.51)

https://downzen.com/en/windows/google-chrome/download/990484451/

ChormeDriver

ChormeDriver(99.0.4844.51)

https://registry.npmmirror.com/binary.html?path=chromedriver/99.0.4844.51/

二,相关代码

1.所用到的包
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import pickle
import time
2.函数体说明

本次代码我把主要的功能用两个函数实现,方便读者理解代码。

spider函数是一个网络爬虫的部分实现,如下:

def spider(url, keyword):  # 两个参数:url即为京东网站,keyword即为爬取的商品名称
    driver = webdriver.Chrome(executable_path=r"ChormeDriver安装路径")  #启动浏览器
    try:
        driver.get(url)  # 将网址传递给driver
        get_goods(driver, keyword)  # 给get_goods传入参数,看下段get_goods代码介绍
    finally:
        driver.quit()  # 清理driver资源

finally:只要 try 里面代码运行结束(或者因异常结束)浏览器都会释放资源关闭。

gets_goods函数说明

input_tag = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, 'key'))
        )
        input_tag.send_keys(keyword)
        input_tag.send_keys(Keys.ENTER) # 在搜索框自动输入keyword

 WebDriverWait第二个参数为等待时间,浏览器会等待10秒,直到等待具有特定ID(京东页面在这里是‘key’)的元素出现在页面上。如果元素在指定的时间内(这里是10秒)变得可用,则代码会向该元素发送文本(keyword变量中的值)和回车键(通过Key.ENTER实现)。

WebDriverWait(driver, 20).until(
            EC.presence_of_all_elements_located((By.CLASS_NAME, 'gl-item'))
        )
        goods = driver.find_elements_by_class_name('gl-item')

 WebDriverWait结合EC.presence_of_all_elements_located来等待页面上所有具有特定类名('gl-item')的元素变得可用。一旦这些元素被检测到存在于DOM中,你就使用find_elements_by_class_name来获取这些元素的列表。

        for page in range(1, 10):   # 切换到当前页面(对于第一页,可自行修改) 
            for good in goods:   # 遍历当前页面的商品  
               detail_url = good.find_element_by_tag_name('a').get_attribute('href')
               p_name = good.find_element_by_css_selector('.p-name em').text.replace('\n', '')
               price_element = good.find_element_by_css_selector('.p-price i')
               price = price_element.text if price_element.text else 'N/A'
               p_commit = good.find_element_by_css_selector('.p-commit a').text


               msg = f"""  
               商品 : {p_name}  
               链接 : {detail_url}  
               价钱 : {price}  
               评论 : {p_commit}  
               """
               print(msg)

detail_ur: 对于每个商品元素(good),找到其内部的第一个<a>标签,并获取其href属性。

p_name: 使用CSS选择器找到商品名称。这里商品名称被包裹在具有类名'p-name'的元素内的<em>标签中。然后,它获取该元素的文本内容并移除其中的换行符。

price_element:使用CSS选择器找到价格元素。这里假设价格被包裹在具有类名'p-price'的元素内的<i>标签中。   

price:获取价格元素的文本内容。如果文本为空(可能没有找到价格或价格为空),则设置价格为'N/A'。

p_commit: 使用CSS选择器找到评论数量或链接。这里京东评论信息被包裹在具有类名'p-commit'的元素内的<a>标签中。然后,它获取该元素的文本内容。

msg: 使用f-string(格式化字符串文字)创建一个包含商品信息的字符串。这个字符串包含了商品名称、链接、价格和评论。

        try:
            next_page_button = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, '下一页'))
            )
            next_page_button.click()  # 找到的“下一页”按钮的点击
            time.sleep(1)  # 等待页面加载
            get_goods(driver, keyword)
        except TimeoutException:
            pass  # 没有下一页按钮,退出递归

 next_page_button

  • 这里使用了Selenium的WebDriverWait对象来等待某个条件成立。具体来说,它等待直到页面上出现一个可以点击的元素,该元素的链接文本包含“下一页”。

  • EC.element_to_be_clickable是一个期望条件(expected condition),它表示元素需要是可见的并且是可点击的。

  • (By.PARTIAL_LINK_TEXT, '下一页')是一个定位器(locator),它指定了要查找的元素应该具有包含“下一页”的链接文本。

  • 如果在10秒内找到了这样的元素,WebDriverWait将返回该元素,并将其存储在next_page_button变量中。

time.sleep:代码使程序暂停1秒。这是一个简单的等待机制,用于确保页面有足够的时间加载新的内容。但是因为页面加载时间可能因各种因素而异,这种方法并不总是可靠或高效的。

get_goods:代码调用了一个名为get_goods的函数(该函数在您提供的代码段中没有定义,但我可以推测它是用于从当前页面获取商品信息的)。它传递了driver(WebDriver对象)和keyword(可能是用于搜索商品的关键字)作为参数。

except TimeoutException:

try代码块中出现TimeoutException(如果在10秒内没有找到可点击的“下一页”按钮)则程序将跳转到这个except块。 pass是一个空操作语句,它在这里表示当发生TimeoutException时,程序什么都不做(即不执行任何操作)。

三,完整代码

下面是整个项目的完整代码:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time



def get_goods(driver, keyword):
    try:
        input_tag = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.ID, 'key'))
        )
        input_tag.send_keys(keyword)
        input_tag.send_keys(Keys.ENTER)

        # 京东会弹出请求登录

        WebDriverWait(driver, 20).until(
            EC.presence_of_all_elements_located((By.CLASS_NAME, 'gl-item'))
        )

        goods = driver.find_elements_by_class_name('gl-item')
        for page in range(1, 10):
            for good in goods:
               detail_url = good.find_element_by_tag_name('a').get_attribute('href')
               p_name = good.find_element_by_css_selector('.p-name em').text.replace('\n', '')
               price_element = good.find_element_by_css_selector('.p-price i')
               price = price_element.text if price_element.text else 'N/A'
               p_commit = good.find_element_by_css_selector('.p-commit a').text


               msg = f"""  
               商品 : {p_name}  
               链接 : {detail_url}  
               价钱 : {price}  
               评论 : {p_commit}  
               """
               print(msg)



        try:
            next_page_button = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, '下一页'))
            )
            next_page_button.click()
            time.sleep(1)  # 等待页面加载
            get_goods(driver, keyword)
        except TimeoutException:
            pass  # 没有下一页按钮,退出递归
    except Exception as error:
        print(f"发生错误: {error}")


def spider(url, keyword):
    driver = webdriver.Chrome(executable_path=r"C:\Users\ASUS\Desktop\chromedriver.exe")
    try:
        driver.get(url)
        get_goods(driver, keyword)
    finally:
        driver.quit()  # 清理driver资源


if __name__ == '__main__':
    url = 'https://www.jd.com/'
    keyword = '输入商品名称'
    spider(url, keyword)

四,关于京东爬取时弹出登录页面 

WebDriverWait(driver, 20).until(
            EC.presence_of_all_elements_located((By.CLASS_NAME, 'gl-item'))
        )

这里设置了在登录页面停留时间为20秒,超时浏览器将释放资源,可自行修改停留时间。

关于实现京东的自动登录,我尝试通过使用用户cookies实现目的,但最后还是失败了,以下是我的部分关于自动登录的代码,供参考借鉴

def load_cookies(driver, cookie_path):
    """加载cookies到driver"""
    if os.path.exists(cookie_path):
        with open(cookie_path, 'rb') as f:
            cookies = pickle.load(f)
            for cookie in cookies:
                driver.add_cookie(cookie)
class CookieLogin():
    def __init__(self):
        self.drive = webdriver.Chrome(executable_path=r"C:\Users\ASUS\Desktop\chromedriver.exe")
        self.url = 'https://passport.jd.com/new/login.aspx?/'

    # 先手动登录,让程序获取到cookie,保存下来
    def getcookie(self):
        # 首先直接访问登录的页面 passport.jd.com
        self.drive.get(self.url)

        # 扫码登录
        # 登录之后的页面会跳转到这里,让浏览器等待,直到url完全匹配
        url = 'https://www.jd.com/'
        WebDriverWait(self.drive, 30).until(EC.url_to_be(url))
        # # 登录之后停2秒
        # time.sleep(2)

### 如何使用 Python 爬虫抓取京东商品数据 #### 技术背景 为了实现从京东平台抓取商品数据的目标,可以采用 Python 编写网络爬虫程序。这不仅有助于收集商品详情、价格变化等信息,还可以用于市场分析和竞争对手研究。以下是具体的技术细节以及注意事项。 --- #### 1. 数据源与目标 京东的商品页面通常由动态加载的内容组成,因此需要特别注意其 HTML 结构和 API 接口的设计方式。可以通过浏览器开发者工具查看请求头和响应体来定位所需的数据接口[^2]。 --- #### 2. 工具与库的选择 在开发过程中需要用到以下主要的 Python 库: - **requests**: 发起 HTTP 请求以获取网页内容。 - **BeautifulSoup (bs4)** 或 **lxml**: 解析静态 HTML 页面结构。 - **selenium**: 如果遇到动态加载内容,则可模拟真实用户的操作行为。 - **pandas**: 对提取到的数据进行清洗和存储处理。 安装这些依赖项可通过 pip 命令完成: ```bash pip install requests beautifulsoup4 lxml selenium pandas ``` --- #### 3. 实现步骤概述 尽管不建议直接分步描述过程,但仍需提及几个核心环节: ##### a) 获取商品列表页 URL 和参数 了解如何构建正确的查询字符串是非常重要的一步。例如,“手机”类目的搜索链接可能形如 `https://search.jd.com/Search?keyword=手机&page=`[^3]。 ##### b) 处理反机制 由于频繁访问可能会触发网站的安全防护措施,所以要设置合理的延时策略或者更换 User-Agent 来伪装成不同的客户端设备类型[^1]。 ##### c) 提取消息主体部分 一旦成功下载了完整的HTML文档之后,就可以运用正则表达式或者是 CSS Selectors 找寻特定标签内的文字节点值。 下面给出一段简单的示范脚本片段供参考学习之用: ```python import requests from bs4 import BeautifulSoup def fetch_jd_product_list(keyword, page_num): base_url = f'https://search.jd.com/Search?keyword={keyword}&page={page_num}' headers = { 'User-Agent': ('Mozilla/5.0 (Windows NT 10.0; Win64; x64)' 'AppleWebKit/537.36 (KHTML, like Gecko)' 'Chrome/91.0.4472.124 Safari/537.36') } response = requests.get(base_url, headers=headers) soup = BeautifulSoup(response.text, 'html.parser') products = [] items = soup.select('.gl-item') # 这里假设每件商品都包裹在一个 .gl-item 的 div 中 for item in items: title_tag = item.find('div', class_='p-name').find('em') price_tag = item.find('strong', class_='J_price') product_info = { 'title': title_tag.string.strip() if title_tag else None, 'price': float(price_tag['data-price']) if price_tag and 'data-price' in price_tag.attrs else None } products.append(product_info) return products if __name__ == '__main__': results = fetch_jd_product_list('笔记本电脑', 1) print(results[:5]) # 输出前五个产品记录作为测试验证 ``` 上述代码仅适用于演示用途,在实际部署之前还需要考虑更多边界情况及异常捕获逻辑。 --- #### 注意事项 - 遵守各站点的服务条款(SoT),确保活动合法性。 - 尊重robots.txt文件指示,避免非法区域扫描。 - 控制频率以免给服务器带来过大压力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值