【爬虫】7.3. CSS位置偏移反爬案例分析与实战

CSS位置偏移反爬案例分析与实战

文章目录

1. 案例分析

上一节学习了Selenium这个自动化测试工具,但这个工具不是万能的,不容易爬取的数据依然存在,例如网页利用CSS控制文字的偏移位置,或者通过一些特殊的方式隐藏关键信息,这都会对数据爬取造成干扰。可以看这一部分代码:

python 复制代码
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

browser = webdriver.Chrome()
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())
复制代码
Wonder
清 白 风 家
法 老 的 宠 妃 终 结 篇 ( 上 下 册 )
( ) 二 己 为 士 知 册 全
年 一 孩 追 些 们 那 女 起 的 我 ,
全 ( 册 三 城 倾 我 ) 非
明 朝 儿 那 事 些

以上是这一段代码的部分输出结果,可以看出来,大部分书名都是乱序的,这是因为网页使用了CSS位置偏移,一下是"清白家风"这一本书的书名部分的代码:

html 复制代码
<h3 data-v-7f1a77ef="" class="m-b-sm name"><span data-v-7f1a77ef="" class="char" style="left: 0px;">
                      清
                    </span><span data-v-7f1a77ef="" class="char" style="left: 16px;">
                      白
                    </span><span data-v-7f1a77ef="" class="char" style="left: 48px;">
                      风
                    </span><span data-v-7f1a77ef="" class="char" style="left: 32px;">
                      家
                    </span></h3>

我们可以看到span中的style属性,表示CSS样式,left的取值各不相同,并且我们在查看span节点的完整样式时候,可以看到:

css 复制代码
.item .bottom .name .char[data-v-7f1a77ef] {
    display: inline-block;
    position: absolute;
}

以上是span节点的两个额外样式,是display和position,而后者表示绝对定位,设置这个样式之后,就可以通过left样式控制span节点在页面中的偏移位置了。了解了为什么会出现这样的情况之后,我们就可以直接通过这个偏移位置来重新安排一下文字的顺序。

这里穿插一些题外话:span节点里面的文本有格式,而pyquery可以省略这些格式,使用get_attribute()或者text就不行了,所以建议复习一下puquery。以下是一个span节点,可以看出格式问题:

html 复制代码
<span data-v-7f1a77ef="" class="char" style="left: 0px;">
                      清
                    </span>

2.爬取实战

思路:利用正则表达式将偏移量提取出来,接着根据偏移量对字体进行排序处理。

python 复制代码
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
import re


def parse_name(name_html):
    has_whole = name_html('.whole')
    if has_whole:
        return name_html.text()
    else:
        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])


browser = webdriver.Chrome()
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_html in names.items():
    name = parse_name(name_html)
    print(name)
browser.close()
相关推荐
Dlrb12113 分钟前
C语言-字符串指针与函数指针
java·c语言·前端
PBitW8 分钟前
组件封装注意事项
前端·vue.js
weiggle13 分钟前
Android 输入事件分发流程:从物理触控到 Activity 的完整旅程
前端
yingyima17 分钟前
开发者必备在线工具集合 2025:实战案例解析
前端
前端毕业班18 分钟前
面试官:实现一个带类型约束的 EventEmitter
前端·面试
卷帘依旧21 分钟前
SPA 中的 Hash 和 History 模式
前端
用户44455436542625 分钟前
AndroidAutoSize使用时遇到的特麻烦bug
前端
茉莉玫瑰花茶29 分钟前
LangGraph 入门教程:构建 AI 工作流 [ 案例三 ]
前端·人工智能·python
scan72433 分钟前
pydantic格式输出
服务器·前端·javascript
ZC跨境爬虫39 分钟前
跟着MDN学HTML_day44:(ProcessingInstruction接口)
前端·javascript·ui·html·媒体