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

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

文章目录

  • CSS位置偏移反爬案例分析与实战
    • 1. 案例分析
    • 2.爬取实战

1. 案例分析

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

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位置偏移,一下是“清白家风”这一本书的书名部分的代码:

<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节点的完整样式时候,可以看到:

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

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

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

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

2.爬取实战

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

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()

你可能感兴趣的:(爬虫,css,前端)