0


使用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),找到其内部的第一个标签,并获取其href属性。

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

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

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

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

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)

本文转载自: https://blog.csdn.net/m0_68276063/article/details/138505625
版权归原作者 理想蛙人 所有, 如有侵权,请联系我们删除。

“使用Selenium+chrome+scrapy完成京东商品信息爬取”的评论:

还没有评论