admin管理员组

文章数量:1794759

Python爬虫:Selenium+BeautifulSoup解析动态HTML页面【附完整代码】

Python爬虫:Selenium+BeautifulSoup解析动态HTML页面【附完整代码】

前言

        前短时间,为了验证公司的验证码功能存在安全漏洞,写了一个爬虫程序抓取官网图库,然后通过二值分析,破解验证码进入系统刷单。 其中,整个环节里关键的第一步就是拿到数据 -- Python 爬虫技。

        今天,我打算把爬虫经验分享一下,因为不能泄露公司核心信,所以我随便找了一个第三方网站——《懂车帝》做演示。为了展示Selenium效果,网站需满足:需要动态加载(下拉)才能获取完整(或更多)数据的网页,如:淘宝,京东,拼多多的商品也都可以。

        通过本篇,你将学会通过Selenium自动化加载HTML的技巧,并利用 BeautifulSoup 解析静态的HTML页面,还有使用 xlwt 插件操作 Excel。

        本文仅教学使用,无任何攻击行为或意向。


正文 一、页面分析 1. 打开页面,提取关键信

        首先,打开“某瓣电影一周新片榜”的页面:www.dongchedi/sales,截图省略了下面列表部分。

        然后,提取榜单里的关键信,如:当前月份,汽车排名,图片链接,汽车名称,汽车品牌,评论数等,这是我们需要爬取的数据,接下来就需要弄清楚他们在 Html 中的位置。

2. 分析Html页面

        Chrome浏览器 - 【F12】检查下 Html 页面结构,找到排行榜数据的具体位置,这对我们后续利用 Selenium 和 BeautifulSoup 解析至关重要。

        下面图片里可以看到,月份信在 “<div class="more_more__z2kQC"></div>” 标签里(篇幅原因,没有展示全),而当月的榜单信在"<li class="list_item__3gOKl">"的标签里,10条 “<tr></tr> ”标签形成一个List集合。

        注意:当前页面第一次进来页面只会加载出10条记录,如果想要获取全量的排行榜数据,我们需要用到 Selenium 技术动态加载页面,直到数据全部加载出来为止。

3. 结果展示

        以我当前的时间为例——“2022年8月”,一共有“TOP542”条数据。


二、代码讲解 1. 导入关键库 import time # time函数 import xlwt # 进行excel操作 import os.path # os读写 from bs4 import BeautifulSoup # 解析html的 from selenium import webdriver # selenium 驱动 from selenium.webdrivermon.by import By from selenium.webdrivermon.keys import Keys # 模仿键盘 from selenium.webdriver.support.wait import WebDriverWait # 导入等待类 from selenium.webdriver.support import expected_conditions as EC # 等待条件 2. Selenium 解析动态Html

        因为当前页面没有明显的元素用来判断拉到什么位置就是底部,所以我的规则是:一直循环,直到连续5次 Keys.PAGE_DOWN(下拉),<li> 标签数量不再增加,就认为已经到底了。为了避免程序计算太快,每次下拉还停顿了0.2秒,实际效果不错。

while (flag): _input.send_keys(Keys.PAGE_DOWN) driver.implicitly_wait(2) elem = driver.find_elements(By.CLASS_NAME, "list_item__3gOKl") len_cur = len(elem) print(len_now, len_cur) if (len_now != len_cur): len_now = len_cur num = 0 elif (len_now == len_cur and num <= 5): num = num + 1 time.sleep(0.5) else: time.sleep(2) break 3. Selenium 转 BeautifulSoup

        根据小编的开发经验,selenium 很擅长模拟和测试,它动态加载的特性是 BeautifulSoup不 具备的。但是,对于取值操作,简单的还好,复杂点的比如:循环<li>标签这种操作,我还是觉得BeautifulSoup更方便。

        在爬虫的世界里,大量有价值的数据都是循环展现的,比如:某排行榜,某商品列表等...所以,Selenium + BeautifulSoup的操作必不可少。

        核心代码也非常简单,直接传入 Selenium 驱动 driver,用 page_source() 就可以啦。

# 获取完整渲染的网页源代码 pageSource = driver.page_source soup = BeautifulSoup(pageSource, 'html.parser') soup.prettify() 4. 保存数据 # 创建workbook对象 book = xlwt.Workbook(encoding="utf-8",style_compression=0) # 创建工作表 sheet = book.add_sheet('懂车帝想月销量排行榜', cell_overwrite_ok=True) col = ("排名", "图片链接", "名称", "品牌", "指导价", "销量") book.save("销量排行榜.xls")
三、完整代码

        细节有待提高,下面的代码大家装好插件,直接拖到本地运行就可以了。

        如果遇到环境问题,未知异常等,请参照博文:关于:Python基础,爬虫,常见异常和面试【篇】(专题汇总)

# -*- codeing = utf-8 -*- import time # time函数 import xlwt # 进行excel操作 import os.path # os读写 from bs4 import BeautifulSoup # 解析html的 from selenium import webdriver # selenium 驱动 from selenium.webdrivermon.by import By from selenium.webdrivermon.keys import Keys # 模仿键盘 from selenium.webdriver.support.wait import WebDriverWait # 导入等待类 from selenium.webdriver.support import expected_conditions as EC # 等待条件 # 获取全量数据的 selenium 驱动 def readHtml(baseurl, flag): print("—————————— Read Html ——————————") # 打开浏览器 driver = webdriver.Chrome() driver.get(baseurl) wait = WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located((By.CLASS_NAME, "tw-mt-12"))) # 动态加载排行榜数据 # 我的规则:一直循环,直到连续5次下拉,<li>标签数量不再增加,则认为已经到底了 num, len_now = 0, 0 _input = driver.find_element(By.CLASS_NAME, "body") while (flag): _input.send_keys(Keys.PAGE_DOWN) driver.implicitly_wait(2) elem = driver.find_elements(By.CLASS_NAME, "list_item__3gOKl") len_cur = len(elem) print(len_now, len_cur) if (len_now != len_cur): len_now = len_cur num = 0 elif (len_now == len_cur and num <= 5): num = num + 1 time.sleep(0.5) else: time.sleep(2) break return driver # 将 selenium 驱动转 bs 形式的 html 页面 def getHtml(driver): print("—————————— Get Html ——————————") # 获取完整渲染的网页源代码 pageSource = driver.page_source soup = BeautifulSoup(pageSource, 'html.parser') soup.prettify() return soup # 从 html 页面爬取数据 def getData(soup): print("—————————— Get Data ——————————") # 1. 时间 dataTime = soup.find('div', class_="more_more__z2kQC").span.text # 2. 数据,查找符合要求的字符串 index = 0 # 排行 datalist = [] # 用来存储爬取的网页信 try: for item in soup.find_all('li', class_="list_item__3gOKl"): data = [] # 保存一条数据用 print(item) # 2.1 生成一条记录 index = index + 1 data.append(index) data.append(item.find('div', class_='tw-p-12').div.div.img["src"]) dd = item.find('div', class_='tw-py-16 tw-pr-12') data.append(dd.div.a.text) data.append(dd.div.span.text) data.append(dd.p.text) data.append(item.find('div', class_='tw-py-16 tw-text-center').div.p.text) # 2.2 存入list datalist.append(data) except Exception as e: print(e) pass return dataTime, datalist # 保存数据到表格 def saveData(datalist, savepath): print("—————————— save ——————————") book = xlwt.Workbook(encoding="utf-8",style_compression=0) # 创建workbook对象 sheet = book.add_sheet(dataTime, cell_overwrite_ok=True) # 创建工作表。sheet页名为dataTime col = ("排名", "图片链接", "名称", "品牌", "指导价", "销量") for i in range(0, len(col)): sheet.write(0, i, col[i]) # 列名 for i in range(0, len(datalist)): # print("第%d条" %(i+1)) # 输出语句,用来测试 data = datalist[i] for j in range(0, len(col)): sheet.write(i+1, j, data[j]) # 数据 if os.path.exists(savepath): # 清空路径 os.remove(savepath) book.save(savepath) # 保存 pass if __name__ == "__main__": print("—————————— 开始执行 ——————————") # 1. 读取url html = readHtml("www.dongchedi/sales", True) # 2. selenium转BeautifulSoup soup = getHtml(html) # 3. 处理Html数据 dataTime, dataList = getData(soup) # 4. 保存数据 saveData(dataList, dataTime + "汽车销量排行总榜.xls") print("—————————— 爬取完毕 ——————————")

本文标签: 爬虫完整页面代码动态