JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战

简介: JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战

CSS位置偏移反爬案例分析与爬取实战
案例
案例网址:https://antispider3.scrape.cener/,页面如下图所示:

image.png

尝试用Selenium获取首页的页面源代码,并解析每个标题的内容:

from selenium import webdriver
from pyquery import PyQuery as pq
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.service import Service

options = webdriver.ChromeOptions()
services = Service('../Selenium/chromedriver')

browser = webdriver.Chrome(service=services, options=options)
browser.get('<https://antispider3.scrape.center/>')
WebDriverWait(browser, 10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.item')))

html = browser.page_source
doc = pq(html)
names = doc('.item .name')
for name in names.items():
    print(name.text())
browser.close()

运行结果如下:

Wonder
清 白 家 风
篇 法 妃 老 的 上 宠 终 册 ) ( 结 下
士 为 己 ) 二 册 知 全 (
, 些 年 们 一 孩 我 的 那 起 女 追
非 我 倾 城 ( 全 三 册 )
朝 事 儿 明 些 那
的 你 忘 和 书 笑 我
全 第 波 集 小 一 卷 王
怦 然 动 心
龙枪编年史(全3册)
龙 枪 册 全 奇 ( ) 三 传
黎 明 之 街
其 知 认 理 学 心 示 启 及
银河帝国2:基地与帝国
银 河 帝 国 : 基 地
级 下 材 全 教 学 - 年 解 语 文 四 小
越界言论(第3卷)

结果中很多标题的文字顺序是乱的,例如《明朝那些事儿》对应的输出结果是“朝事儿明些那”,这是怎么回事?

排查
我们去浏览器里面研究一下源代码,如图所示:

image.png

发现一个字对应一个span节点,这个节点本身的顺序也是乱的,所以用pyquery提取出来的标题内容乱序就不足为怪了。

源代码中的文字本身是乱的,那为什么在网页上看到的标题是正确的?这是因为网页本身利用CSS控制了文字的偏移位置,什么意思呢?观察下源代码:

<h3 data-v-7f1a77ef="" class="m-b-sm name">
<span data-v-7f1a77ef="" class="char" style="left: 80px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 16px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 0px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 48px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 32px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 64px;"></span>
  </h3>

可以发现,每个span节点都有一个style属性,表示CSS样式,left的取值各不相同。另外,在浏览器中观察一下每个span节点的完整样式,如图所示:

image.png

span节点还有两个额外的样式,是display: inline-block和position:absolute,或者比较重要,代表绝对定位,设置这个样式后,就可以通过修改left的值控制span节点在页面中的偏移位置了,例如left:0px代表不偏移;left:16px代表从左边算起向右偏移16像素,于是节点就到了右边。源代码中,“明”子的偏移量是0,“朝”字的偏移量是16像素,“那”字的偏移量是32像素,依此类推,最终标题的视觉效果就变成了“明朝那些事儿”。

爬取
了解了基本原理后,只需要获取每个span节点的style属性,提取出偏移值,然后排序就可以得到最终结果了。先实现基本的提取方法:

from selenium import webdriver
from pyquery import PyQuery as pq
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.service import Service
import re

def parse_name(name_html):
    chars = name_html('.char')
    items = []
    for char in chars.items():
        items.append({
   
            'text': char.text().strip(),
            'left': int(re.search('(\\d+)px', char.attr('style')).group(1))
        })
    items = sorted(items, key=lambda x:x['left'], reverse=False)
    return ''.join([item.get('text') for item in items])

options = webdriver.ChromeOptions()
services = Service('../chromedriver')

browser = webdriver.Chrome(service=services, options=options)
browser.get('<https://antisipder3.scrape.center/>')
WebDriverWait(browser, 10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.item')))
html = browser.page_source
doc = pq(html)
names = doc('.item .name')
for name_html in names.items():
    name = parse_name(name_html)
    print(name)
browser.close()

这里定义了一个parse_name方法,用来解析页面源代码得到最终的标题。它接收一个参数name_html,就是标题的HTML文本,类似这样:

<h3 data-v-7f1a77ef="" class="m-b-sm name">
<span data-v-7f1a77ef="" class="char" style="left: 80px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 16px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 0px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 48px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 32px;"></span>
<span data-v-7f1a77ef="" class="char" style="left: 64px;"></span>
  </h3>

在parse_name方法中,我们首先选取.char节点,将其赋值为chars变量,然后遍历chars变量,其中每个条目各自对应一个span节点,其内容类似于:

<span data-v-7f1a77ef="" class="char" style="left: 16px"></span>

在parse_name方法中,我们首先选取.char节点,将其赋值为chars变量,然后遍历chars变量, 其中每个条目各自对应一个span节点,其内容类似于:

<span data-v-7f1a77ef="" class="char" style="left: 16px"></span>

遍历过程中,提取了span节点的文本内容作为字典的text属性,还提取了style属性的内容,例如这里提取的是16px,并用正则表达式提取了其中的数值,这里是16,将其赋值为字典的left属性。

遍历结束后,items的结果类似下面这样:

[{
   'text': '些', 'left': 48}, {
   'text': '事', 'left': 64}, {
   'text': '儿', 'left': 80}, {
   'text': '那', 'left': 32}, {
   'text': '朝', 'left': 16}, {
   'text': '明', 'left': 0}]

面对这样的结果,怎么排序呢?直接调用sorted方法就行,它有两个参数,一个是key,用来指定根据什么排序,这里我们直接使用lambda表达式提取span节点的left属性,所以最终结果是根据left的值排序而得;另一个参数是reverse,用来指定排序方式,此处将其设置为False,表示从小到大排序。排序完的items变成了这样:

[{
   'text': '明', 'left': 0}, {
   'text': '朝', 'left': 16}, {
   'text': '那', 'left': 32}, {
   'text': '些', 'left': 48}, {
   'text': '事', 'left': 64}, {
   'text': '儿', 'left': 80}]

最后将其中的text值提取出来并拼接,就得到了最终结果:

清白家风
法老的宠妃终结篇(上下册)
士为知己(全二册)
那些年,我们一起追的女孩
非我倾城(全三册)
明朝那些事儿
我和你的笑忘书
王小波全集第一卷
怦然心动

龙枪传奇(全三册)
黎明之街
认知心理学及其启示

银河帝国:基地
小学教材全解-四年级语文下
相关文章
|
12天前
|
Web App开发 监控 JavaScript
监控和分析 JavaScript 内存使用情况
【10月更文挑战第30天】通过使用上述的浏览器开发者工具、性能分析工具和内存泄漏检测工具,可以有效地监控和分析JavaScript内存使用情况,及时发现和解决内存泄漏、过度内存消耗等问题,从而提高JavaScript应用程序的性能和稳定性。在实际开发中,可以根据具体的需求和场景选择合适的工具和方法来进行内存监控和分析。
|
25天前
|
JavaScript 前端开发 Go
CSS 与 JS 对 DOM 解析和渲染的影响
【10月更文挑战第16天】CSS 和 JS 会在一定程度上影响 DOM 解析和渲染,了解它们之间的相互作用以及采取适当的优化措施是非常重要的。通过合理的布局和加载策略,可以提高网页的性能和用户体验,确保页面能够快速、流畅地呈现给用户。在实际开发中,要根据具体情况进行权衡和调整,以达到最佳的效果。
|
30天前
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理与实战
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理与实战
|
12天前
|
前端开发 JavaScript
如何在 JavaScript 中访问和修改 CSS 变量?
【10月更文挑战第28天】通过以上方法,可以在JavaScript中灵活地访问和修改CSS变量,从而实现根据用户交互、页面状态等动态地改变页面样式,为网页添加更多的交互性和动态效果。在实际应用中,可以根据具体的需求和场景选择合适的方法来操作CSS变量。
|
3天前
|
缓存 前端开发 JavaScript
优化CSS和JavaScript加载
Next.js和Nuxt.js在优化CSS和JavaScript加载方面提供了多种策略和工具。Next.js通过代码拆分、图片优化和特定的CSS/JavaScript优化措施提升性能;Nuxt.js则通过代码分割、懒加载、预渲染静态页面、Webpack配置和服务端缓存来实现优化。两者均能有效提高应用性能。
|
3天前
|
前端开发 JavaScript
用HTML CSS JS打造企业级官网 —— 源码直接可用
必看!用HTML+CSS+JS打造企业级官网-源码直接可用,文章代码仅用于学习,禁止用于商业
27 1
|
8天前
|
数据采集 JavaScript 搜索推荐
服务器端渲染(SSR)(Nuxt+Next.js)
服务器端渲染(SSR)技术在服务器上生成页面HTML,提升首屏加载速度和SEO效果。Nuxt.js和Next.js分别是基于Vue.js和React.js的流行SSR框架。Nuxt.js提供自动化路由管理、页面级数据获取和布局系统,支持SSR和静态站点生成。Next.js支持SSR、静态生成和文件系统路由,通过`getServerSideProps`和`getStaticProps`实现数据获取。SSR的优点包括首屏加载快、SEO友好和适合复杂页面,但也会增加服务器压力、开发限制和调试难度。选择框架时,可根据项目需求和技术栈决定使用Nuxt.js或Next.js。
|
8天前
|
运维 监控 JavaScript
鸿蒙next版开发:分析JS Crash(进程崩溃)
在HarmonyOS 5.0中,JS Crash指未处理的JavaScript异常导致应用意外退出。本文详细介绍如何分析JS Crash,包括异常捕获、日志分析和典型案例,帮助开发者定位问题、修复错误,提升应用稳定性。通过DevEco Studio收集日志,结合HiChecker工具,有效解决JS Crash问题。
24 4
|
8天前
|
前端开发 JavaScript 安全
HTML+CSS+JS密码灯登录表单
通过结合使用HTML、CSS和JavaScript,我们创建了一个带有密码强度指示器的登录表单。这不仅提高了用户体验,还帮助用户创建更安全的密码。希望本文的详细介绍和代码示例能帮助您在实际项目中实现类似功能,提升网站的安全性和用户友好性。
19 3
|
13天前
|
前端开发 JavaScript UED
如何使用 JavaScript 动态修改 CSS 变量的值?
【10月更文挑战第28天】使用JavaScript动态修改CSS变量的值可以为页面带来更丰富的交互效果和动态样式变化,根据不同的应用场景和需求,可以选择合适的方法来实现CSS变量的动态修改,从而提高页面的灵活性和用户体验。