0


[Python 爬虫] Selenium爬取电影《749局》豆瓣热评

版本前瞻:
为防止因为版本不同导致各位遇到奇奇怪怪的错误,特将版本列此,以供参考

Python=3.9  selenium=4.9.1 MongoDB v4.2.24

文章目录

1.环境准备

具体Selenium环境配置请看我的上一篇博客
[Python 爬虫] Selenium及Miniconda3安装

2.确定目标网页及数据范围

通过Selenium自动化测试框架控制浏览器行为
从豆瓣首页打开至电影 749局 短评-热评-全部 并对所有评论进行爬取749局 短评-热评-全部
开始页面
最终页面

3.检查网站的使用条款和 robots.txt (君子协议)

  • 首先仔细查看目标网站的使用条款和隐私政策。有些网站明确禁止爬虫访问,违反规定可能会导致法律问题。
  • 其次查看 robots.txt(不讲武德的直接看下一步)在这里插入图片描述

1.对通用爬虫的限制

  • 禁止爬取的路径包括:/subject_search、/amazon_search、fsearch、fgroup/search、fevent/search、fcelebrities/search、/location/drama/search、fforum/、fnew_subject、fservice/iframe、fj、flink2/、frecommend/、/doubanapp/card、/update/topic/、fsharef、/people//collect、/people//wish、/people//all。
  • 允许爬取的文件为fads.txt。*
  • 提供了两个网站地图地址:https://fwww.douban.com/sitemap_index.xml和https://fwww.douban.com/sitemap_updated_index.xml。*
  • 建议通用爬虫抓取间隔为 5 秒(Crawl-delay: 5)。

2.对豌豆荚爬虫的限制

  • 禁止豌豆荚爬虫(Wandoujia Spider)爬取任何以f开头的路径。

3.对谷歌广告爬虫的限制

  • 禁止谷歌广告爬虫(Mediapartners-Google)爬取/subject_search、/amazon_search、/search、fgroup/search、fevent/search、fcelebrities/search、/location/drama/search、fj路径。

4.代码实现

①.创建构造方法
import time # 用于控制浏览器加载时间 防止爬取速度过快出现异常from random import randint 
from pymongo import MongoClient # 使用mongoDB进行数据存储from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC
# By类用于指定在网页中定位元素的方式# WebDriverWait 类用于等待特定条件的出现# expected_conditions 模块提供了一系列预定义的条件,用于在 WebDriverWait 中等待特定的网页状态或元素状态classDb_Movie749():
    client = MongoClient('localhost',27017)
    collection = client['py_spider']['Db_749commends']def__init__(self):# 创建浏览器配置对象
        self.chrome_options = webdriver.ChromeOptions()# 页面全屏打开
        self.chrome_options.add_argument("--start-maximized")
        self.prefs ={# 此设置针对的是由管理员或策略管理的内容中的弹出窗口。同样设置为0也是禁止显示弹出窗口"profile.managed_default_content_settings.popups":0,# 阻止所有图像自动加载 加快页面打开速度"profile.managed_default_content_settings.images":2,}
        self.chrome_options.add_experimental_option('prefs', self.prefs)# 创建驱动器对象
        self.browser = webdriver.Chrome(options=self.chrome_options)
②.使用selenium打开目标页面

Selenium框架元素定位方法
在定位元素时,需要借助selenium框架提供的定位工具来进行元素定位。元素定位工具导入路径如下:
from selenium.webdriver.common.by import By
为了能够点击某个按钮,此时我们就需要准确无误的定位到需要的元素。元素定位主要分为以下两种:
● 单个节点(返回是一个对象)
○ find_element(By.ID, ‘定位规则’)
通过元素唯一的ID属性定位单个元素
○ find_element(By.NAME, ‘定位规则’)
依元素NAME属性值定位单个元素
○ find_element(By.XPATH, ‘定位规则’)
借助强大的XPATH表达式定位单个元素,可依据元素层次结构、属性等多条件精准定位
○ find_element(By.LINK_TEXT, ‘定位规则’)
根据链接完整文本内容定位单个链接元素,要求文本完全匹配。
○ find_element(By.PARTIAL_LINK_TEXT, ‘定位规则’)
按链接文本部分内容定位单个链接元素,适用于已知部分文本的情况。
○ find_element(By.TAG_NAME, ‘定位规则’)
基于元素标签名定位单个元素,但可能因同名标签较多需进一步筛选。
○ find_element(By.CLASS_NAME, ‘定位规则’)
通过元素类名定位单个元素,注意类名可能不唯一,需确保能准确找到目标。
○ find_element(By.CSS_SELECTOR, ‘定位规则’)
运用CSS选择器定位单个元素,能结合多种条件灵活定位元素。
● 多个节点(返回是一个列表)
○ find_elements(By.ID, ‘定位规则’)
○ find_elements(By.NAME, ‘定位规则’)
○ find_elements(By.XPATH, ‘定位规则’)
○ find_elements(By.LINK_TEXT, ‘定位规则’)
○ find_elements(By.PARTIAL_LINK_TEXT, ‘定位规则’)
○ find_elements(By.TAG_NAME, ‘定位规则’)
○ find_elements(By.CLASS_NAME, ‘定位规则’)
○ find_elements(By.CSS_SELECTOR, ‘定位规则’)

注意!!!
在 Selenium 4.0 版本开始,对元素定位方法进行了一些调整和简化,使用find_element和find_elements系列方法来进行元素定位!!!
在这里插入图片描述

流程如下:

在这里插入图片描述
1、通过 F12 进行元素定位找到搜索框对应的页面标签输入 749局
在这里插入图片描述

defTargetWeb(self):# 打开豆瓣电影首页
    self.browser.get('https://movie.douban.com/')# 设置等待条件,等待搜索输入框元素可见,最长等待10秒
    wait = WebDriverWait(self.browser,10)
    ele_input = wait.until(EC.visibility_of_element_located((By.ID,"inp-query")))# 在搜索输入框中输入电影名称"749局"
    ele_input.send_keys("749局")

2、找到 “搜索” 的页面标签 selenium通过 By.XPATH 定位进行对浏览器的操作
在这里插入图片描述

# 设置等待条件,等待搜索按钮元素可见,最长等待10秒
    ele_button = wait.until(EC.visibility_of_element_located((By.XPATH,"//div[@class='inp-btn']/input")))# 点击搜索按钮
    ele_button.click()
    time.sleep(2)

3、通过超链接文本定位电影链接元素
在这里插入图片描述

# 设置等待条件,通过超链接文本定位电影链接元素,最长等待10秒
    movie_button = wait.until(EC.visibility_of_element_located((By.LINK_TEXT,'749局 (2024)')))# 点击电影链接
    movie_button.click()

4、进入该页面后需要控制浏览器向下滑动!!! 找到 目标位置****“749的短评-热门”

如果不控制浏览器向下滑动就通过selenium对 目标位置 进行元素定位是无法进行的

在这里插入图片描述
在这里插入图片描述

# 执行JavaScript代码向下滚动页面1500像素
    js_code =f'window.scrollTo(0, 1500);'
    self.browser.execute_script(js_code)# 随机等待1到2秒,模拟用户操作的随机性
    time.sleep(randint(1,2))
③.开始爬取

1、进入到目标页面,开始爬取,用户及对应的评论,使用字典进行储存

defparse_comments(self):
        comments_info = self.browser.find_elements(By.XPATH,"//div[@id='comments']/div[@class='comment-item ']")for comment in comments_info:
            name = comment.find_element(By.XPATH,".//div[@class='comment']//span[@class='comment-info']/a").text
            comment = comment.find_element(By.XPATH,'.//p/span[@class="short"]').text
            item ={'name': name,'comment': comment
            }

2、使用MongoDB进行数据存储

# 数据存储defsave_info(self,item):
        self.collection.insert_one(item)

3、下滑至页面底部通过元素定位到 “后页” 当前页面爬取完毕后进行翻页,数据量:一共五页 一页二十条

这里同样要注意先要先下滑到页面显示出 “后页” 后才能对其进行定位

在这里插入图片描述

# 控制页面下滑defdrop_down(self):for num inrange(1,6):
            js_code =f'window.scrollBy(0, {num *500});'
            self.browser.execute_script(js_code)
            time.sleep(randint(1,2))# 翻页defnext_page(self):try:
            next_button = self.browser.find_element(By.XPATH,'//div[@id="paginator"]/a[@class="next"]')
            next_button.click()
            self.parse_comments()except Exception as e:print('最后一页:',e)
            self.browser.quit()# 翻至最后一页关闭页面

4、最后通过主函数控制代码逻辑

defmain(self):
        self.TargetWeb()
        self.parse_comments()

4.完整代码及爬取结果展示

import time
from random import randint
from pymongo import MongoClient
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

classDb_Movie749():
    client = MongoClient('localhost',27017)
    collection = client['py_spider']['Db_749commends']def__init__(self):# 创建浏览器配置对象
        self.chrome_options = webdriver.ChromeOptions()# 页面全屏打开
        self.chrome_options.add_argument("--start-maximized")
        self.prefs ={# 此设置针对的是由管理员或策略管理的内容中的弹出窗口。同样设置为0也是禁止显示弹出窗口"profile.managed_default_content_settings.popups":0,# 阻止所有图像自动加载"profile.managed_default_content_settings.images":2,}
        self.chrome_options.add_experimental_option('prefs', self.prefs)# 创建驱动器对象
        self.browser = webdriver.Chrome(options=self.chrome_options)# 请求页面并进行搜索 为确保要定位的页面元素已经加载出来通过创建wait对象等待defTargetWeb(self):try:
            self.browser.get('https://movie.douban.com/')
            wait = WebDriverWait(self.browser,10)
            ele_input = wait.until(EC.presence_of_element_located((By.ID,"inp-query")))
            ele_input.send_keys("749局")
            ele_button = wait.until(EC.presence_of_element_located((By.XPATH,"//div[@class='inp-btn']/input")))
            ele_button.click()
            time.sleep(2)# 通过超链接文本进行定位
            movie_button = wait.until(EC.presence_of_element_located((By.LINK_TEXT,'749局 (2024)')))# 通过xpath定位# movie_button = wait.until(EC.presence_of_element_located((By.XPATH,"//a[@href='https://movie.douban.com/subject/26747919/']")))
            movie_button.click()# 向下翻页
            js_code =f'window.scrollBy(0, 1500);'
            self.browser.execute_script(js_code)
            time.sleep(randint(1,2))# 对短评进行定位
            comments_button = wait.until(EC.presence_of_element_located((By.LINK_TEXT,'热门')))
            comments_button.click()# 进行休眠
            time.sleep(randint(1,3))except Exception as e:print(f"在请求搜索过程中出现错误: {e}")defdrop_down(self):for num inrange(1,6):
            js_code =f'window.scrollBy(0, {num *500});'
            self.browser.execute_script(js_code)
            time.sleep(randint(1,2))# 数据提取defparse_comments(self):
        self.drop_down()
        comments_info = self.browser.find_elements(By.XPATH,"//div[@id='comments']/div[@class='comment-item ']")for comment in comments_info:
            name = comment.find_element(By.XPATH,".//div[@class='comment']//span[@class='comment-info']/a").text
            comment = comment.find_element(By.XPATH,'.//p/span[@class="short"]').text
            item ={'name': name,'comment': comment
            }
            self.save_info(item)print(item)
        self.next_page()# 数据存储defsave_info(self,item):
        self.collection.insert_one(item)# 翻页defnext_page(self):try:
            next_button = self.browser.find_element(By.XPATH,'//div[@id="paginator"]/a[@class="next"]')
            next_button.click()
            self.parse_comments()except Exception as e:print('最后一页:',e)
            self.browser.quit()defmain(self):
        self.TargetWeb()
        self.parse_comments()if __name__ =='__main__':
    db_Movie = Db_Movie749()
    db_Movie.main()

在这里插入图片描述

5.异常情况

当访问次数过于频繁,当前IP将不能直接访问第二页以后的评论需要登录才能正常访问,但是由于selenium添加cookie的方法相当鸡肋,无法满足添加所需的cookie信息访问网页以绕过登录,所以如果出现异常情况,通常需要等待一段时间或者可以通过添加代理的方式进行爬取
在这里插入图片描述

标签: python 爬虫 selenium

本文转载自: https://blog.csdn.net/weixin_62274638/article/details/143751097
版权归原作者 小白要努力变强. 所有, 如有侵权,请联系我们删除。

“[Python 爬虫] Selenium爬取电影《749局》豆瓣热评”的评论:

还没有评论