先补充一下之前一篇 json数据类型 & Xpath 用法 & 爬取豆瓣电影信息 的代码。
在这篇文章的最后展示了豆瓣电影Top250榜单爬取,但是只爬取了一页,而且是用打印的方式输出来的。现在补充一下该网站的多页抓取,并且将信息存在文件中的完整代码,如下
python
# coding=utf-8
import requests
from lxml import etree
for j in range(200):
print(f'第{j+1}页')
url = f'https://movie.douban.com/top250?start={j * 25}&filter='
headers = {
'Cookie': 'bid=jCUu7AAdMaA; _pk_id.100001.4cf6=505329432dc1a06a.1763299315.; _pk_ses.100001.4cf6=1; ap_v=0,6.0; __utma=30149280.1446375450.1763299316.1763299316.1763299316.1; __utmb=30149280.0.10.1763299316; __utmc=30149280; __utmz=30149280.1763299316.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utma=223695111.461199426.1763299316.1763299316.1763299316.1; __utmb=223695111.0.10.1763299316; __utmc=223695111; __utmz=223695111.1763299316.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __yadk_uid=6GRM003EC1i9mMKxNsqKC0JaVR3hEj7r; ll="108296"; _vwo_uuid_v2=DA168F7361E5C19F8ED9C8BF852D64C3E|a3d0ec573f3e1d861764a76065cc10f6',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36'
}
res = requests.get(url, headers=headers)
tree = etree.HTML(res.text)
list_data = tree.xpath('//div[@class="info"]')
for i in list_data:
movies = []
movies_dict = {}
title = i.xpath('./div[@class="hd"]/a/span[1]/text()')[0].strip()
movies_dict['标题'] = title
people = i.xpath('.//div[@class="bd"]/p[1]/text()[1]')[0].strip().replace('\n', '').replace('\xa0', '')
movies_dict['导演和演员'] = people
score = i.xpath('.//span[@class="rating_num"]/text()')[0].strip()
movies_dict['评分'] = score
quote = i.xpath('.//p[@class="quote"]/span/text()')
if quote:
quote = quote[0].strip()
else:
quote = '无简介'
movies_dict['简介'] = quote
movies.append(movies_dict)
with open('top豆瓣电影前200页.txt', 'a') as f:
f.write(str(movies)+'\n')
接下来介绍 Selenium:一般来说,使用协议抓取搞不定的,就可以用 Selenium 的方式去做
传统爬虫(基于 requests)
传统爬虫工作流程
传统爬虫通常借助 requests 库来实现,其核心步骤如下:
1、找到目标数据所在的请求:在浏览器中使用开发者工具(如 Chrome 的网络面板),分析网页加载过程中发出的各种请求,找出包含目标数据的请求。这可能需要对不同类型的请求(如 GET、POST 请求)和请求参数进行分析
2、发起请求:使用 requests 库向目标 URL 发送 HTTP 请求。
3、得到响应数据:请求发送后,服务器会返回响应数据。可以通过 response.text 获取响应的文本内容,或者使用 response.json() 处理 JSON 格式的响应。
4、解析数据:根据响应数据的格式(如 HTML、JSON 等),使用相应的解析库进行解析。例如,对于 HTML 数据,可以使用 BeautifulSoup 或 lxml ;对于 JSON 数据,可以直接使用 Python 的字典操作。
5、保存数据:将解析后的数据保存到本地文件或数据库中。可以使用 csv 、 json 等模块进行文件操作,或者使用数据库连接库(如 pymysql )将数据存入数据库。
传统爬虫的特点
传统爬虫以客户端的身份通过请求获取服务端返回的数据,主要依赖网络面板来获取响应数据。它适用于数据接口清晰、数据结构相对简单的网站,但对于一些需要用户交互、动态加载数据的网站,传统爬虫可能无法很好地处理
自动化爬虫(基于 selenium)
自动化爬虫工作流程
自动化爬虫使用 Selenium 库,它可以直接模拟用户在浏览器中的操作,工作流程如下:
1、无需寻找数据请求:可以直接使用浏览器地址栏的 URL 打开网页,实现所见即所得。因为 Selenium 会直接在浏览器中加载网页,无需像传统爬虫那样分析数据所在的请求。
2、直接操作浏览器:代码以模拟用户的身份直接操控浏览器,通过元素面板获取数据。以下是一个简单的示例:
Selenium 的使用要点
驱动程序(Chrome 浏览器)
要使用 Selenium 操作浏览器,必须安装对应的驱动程序,并且驱动程序的版本要与浏览器版本对应。可以从谷歌驱动获取 Chrome 浏览器的驱动程序。具体步骤如下:
查看谷歌浏览器版本:在浏览器地址栏输入 chrome://version/ ,找到大版本号


第一行就是:142.0.7444.176 (正式版本) (arm64) ,版本号为:142.0.7444.176 (arm64)
找到版本号对应的位置,根据自己的系统型号复制 chromedriver 的下载链接到浏览器窗口中打开:低版本、高版本,我的对应的是高版本,所以去高版本这个页面找了,找到对应的型号复制地址然后打开网页

下载后得到的是压缩包,先解压,解压后找到 chromedriver.exe 文件。

mac 电脑如果遇到 未打开"chromedriver" Apple 无法验证 "chromedriver" 是否包含可能危害Mac安全或泄漏隐私的恶意软件。 这个情况,请参阅 Mac 使用手册
驱动程序(Edge 浏览器)
打开 Edge 浏览器,找到右上角三个点


找到"帮助与反馈",点击"关于 Microsoft Edge"查看版本

在这里

直接搜索 "Edge 浏览器驱动",就在官网上,搜出来是这个样子的

往下划拉划拉,会看到好多版本的驱动,我们下载这个稳定版本的

下载之前最后再比对一下版本号,发现一模一样(小数点最后一两位有一点儿差别也没关系,但一定要保证前面的地方都一样,142.0.3595 这个地方都需要一致),可以下载


点击 x64 就行了,直接下载,下载到哪里都行。我在D盘有一个专门存下载包的地方,我下载到了这里:D:\soft_install_packages,解压一下,从左边压缩包变成右边文件夹


然后我们需要找一下路径,这时候安装不能乱放。按住快捷键:win + R,打开窗口,输入cmd,然后回车

输入where python,查看路径

把路径复制下来

粘到这里,粘到这种程度就行了,按回车,就进去了

把刚才下载的解压包打开,发现有一个 driver 的程序

把这个程序直接拖过来

拖过来之后就是这样子

基本操作示例(以 Edge 为例)
新建文件 测试.py

安装第三方库
安装 Selenium 第三方模块:可以使用 pip 命令安装 Selenium ,建议指定版本进行安装。
bash
pip install selenium==4.0
4.0 版本就可以了。不建议安装太高的版本,遇到问题不好解决,也没有大佬遇到过,只能自己解决。等能力到了再去安装最新版本。安装好之后,接下来就可以用了
使用自动化打开百度搜索
首先从 selenium 导入驱动,下一步是实例化的过程,然后访问网页
python
from selenium import webdriver
wb = webdriver.Edge()
wb.get('https://www.baidu.com')
运行之后,edge 浏览器自动打开了百度搜索界面
豆瓣自动搜索
网址是:https://movie.douban.com/top250
新建一个文件:豆瓣自动搜索.py

想在搜索框搜索成龙,像这样子
我们希望可以自动化搜索。
把代码粘过去,改一下网址,使用 find_element() 获取标签,在最开头的位置导入 By。搜索的位置需要知道,右键网页点击审查元素

最好是把它挪下面去,点右上角三个小点,停靠侧点靠至底部
然后它就跑到下面来了
找一下窗口所在的地方,定位到了这里
把我这行代码粘过来瞧瞧
<input id="inp-query" name="search_text" size="22" maxlength="60" placeholder="搜索电影、电视剧、综艺、影人" value="" autocomplete="off">
可以用 id,也可以用 name。这次用 name
找到 input 标签,然后找到这个符号,@name="search_text",匹配成龙,send_keys('成龙')
python
wb.find_element(By.XPATH, '//input[@name="search_text"]').send_keys('成龙')
这是在搜索框自动输入成龙,输入之后还想搜索一下,接下来实现自动点击的效果。找一下搜索框对应的 HTML 代码
用 input 也行,用上面的 class 也可以。这次用 class
python
wb.find_element(By.XPATH, '//div[@class="inp-btn"]/input').click()
完整在豆瓣搜索成龙代码如下
python
from selenium import webdriver
from selenium.webdriver.common.by import By
wb = webdriver.Edge()
wb.get('https://movie.douban.com/top250')
wb.find_element(By.XPATH, '//input[@name="search_text"]').send_keys('成龙')
wb.find_element(By.XPATH, '//div[@class="inp-btn"]/input').click()
关闭网页,执行一下,可以成功弹出
窗口切换
比如,可能会有需求,要打开很多网址,使用 execute_script(),在打开豆瓣之后再打开一个百度搜索窗口
python
from selenium import webdriver
wb = webdriver.Edge()
wb.get('https://movie.douban.com/top250')
wb.execute_script('window.open("https://www.baidu.com")')
再多打开几个窗口,4399小游戏,csdn,唯品会
python
from selenium import webdriver
wb = webdriver.Edge()
wb.get('https://movie.douban.com/top250')
wb.execute_script('window.open("https://www.baidu.com")')
wb.execute_script('window.open("https://www.4399.com")')
wb.execute_script('window.open("https://www.csdn.com")')
wb.execute_script('window.open("https://www.vip.com")')
执行一下,5个窗口都打开了
我们可以看到展示出来的是唯品会网站,是最后一个打开的
但程序不是这么认为的,查看一下当前的活动窗口,发现是豆瓣
查看当前活动窗口代码如下(获取当前的句柄)
python
print(wb.current_window_handle)
print(wb.title)
这就会引发一个问题,由于展示出来的是唯品会,我们开始对它进行抓取,对它解析,代码都写好了,但是去执行的时候发现,无论怎么弄唯品会里的代码都没办法执行,是因为焦点有问题。因为当前活动窗口还停留在豆瓣。看上去是在唯品会,实际程序停留在豆瓣
这个时候就涉及到了窗口的切换,需要把窗口切换到对应的位置上去,不能用眼睛去看打开了几个窗口,要做的是获取一下窗口到底有哪些
python
from selenium import webdriver
wb = webdriver.Edge()
wb.get('https://movie.douban.com/top250')
wb.execute_script('window.open("https://www.baidu.com")')
wb.execute_script('window.open("https://www.4399.com")')
wb.execute_script('window.open("https://www.csdn.com")')
wb.execute_script('window.open("https://www.vip.com")')
wins = wb.window_handles
print(wins)
print(wb.current_window_handle)
print(wb.title)
执行之后,我们可以看到这5个窗口
通过 wb.switch_to.window(wins[1]) 来切换一下,索引0是豆瓣,我们选择wins[1]来看一下
python
from selenium import webdriver
wb = webdriver.Edge()
wb.get('https://movie.douban.com/top250')
wb.execute_script('window.open("https://www.baidu.com")')
wb.execute_script('window.open("https://www.4399.com")')
wb.execute_script('window.open("https://www.csdn.com")')
wb.execute_script('window.open("https://www.vip.com")')
wins = wb.window_handles
print(wins)
# 查看当前句柄
print(wb.current_window_handle)
print(wb.title)
wb.switch_to.window(wins[1])
print(wb.title)
执行之后发现打开的是csdn
它并不是按照打开网址的顺序来的。这里面的句柄是无序的
所以在爬取数据的时候,尽量不要开多个网站,最多3个。开了多网站之后一定要确定一下句柄的位置,不在目标位置的话,需要通过 wb.switch_to.window() 来切换到目标位置