我知道我可以使用帶有諸如 bs4 之類的庫的 css 選擇器來提取元素。但我有一個問題,我不知道用于樣式化我需要提取的元素的 css 類的名稱,但我知道所有這些元素都有適用于它們的通用規則(“位置:固定;”在我的情況下)。有沒有什么方便的方法(一些圖書館)可以用來做到這一點?
uj5u.com熱心網友回復:
除非 HTML 源代碼具有行內樣式,否則您將無法輕松確定每個元素具有哪些樣式規則,從而使過濾程序更加復雜。下面的解決方案分為兩部分:
- 從目標頁面的源代碼中,使用 .css 請求和決議 CSS 樣式表
tinycss。 - 然后,該站點被打開,
selenium并將已定義json的樣式規則傳遞給通過driver.execute_script. 這樣,element.matches可以利用內置的 Javascript 方法在 CSS 路徑匹配檢測中產生顯著的加速:
import requests, urllib.parse, tinycss
import itertools
from bs4 import BeautifulSoup as soup
base_url = 'https://stackoverflow.com/questions/tagged/python' #replace with your own target link
def css(link):
parser = tinycss.make_parser('page3')
stylesheet = parser.parse_stylesheet(requests.get(link).text)
return [[i.selector.as_css(), [[j.name, j.value.as_css()] for j in i.declarations]]
for i in stylesheet.rules if not isinstance(i, tinycss.css21.MediaRule)]
css_links = [css(urllib.parse.urljoin(base_url, i['href'])) for i in \
soup(requests.get(base_url).text, 'html.parser').select('link[rel="stylesheet"]')]
現在,加載目標頁面selenium:
from selenium import webdriver
import re, json
d = webdriver.Chrome('/path/to/chromedriver')
d.get(base_url)
rules = ['position:fixed', 'text-align: left'] #your rule list
new_rules = [re.split('\:(?:\s )*', i) for i in rules]
classes = d.execute_script('''
var target_rules = JSON.parse(arguments[0]);
var selectors = JSON.parse(arguments[1]);
function* matching_rules(elem){
for (var i of selectors){
for (var [s, rules] of i){
try{
if (elem.matches(s)){
yield* rules
}
}
catch(e){
}
}
}
}
function* get_classes(elem){
if (elem.getAttribute('class')){
for (var rule of matching_rules(elem)){
if (target_rules.map(JSON.stringify).includes(JSON.stringify(rule))){
yield [elem.getAttribute('class'), rule]
}
}
}
for (var i of elem.children){
yield* get_classes(i);
}
}
return [...get_classes(document.querySelector('body'))]
''', json.dumps(new_rules), json.dumps(css_links))
print(classes)
輸出:
[['top-bar js-top-bar top-bar__network', ['position', 'fixed']], ['topbar-dialog leftnav-dialog js-leftnav-dialog dno', ['text-align', 'left']], ['s-spinner s-spinner__sm fc-orange-400', ['text-align', 'left']], ['topbar-dialog siteSwitcher-dialog dno', ['text-align', 'left']], ['container', ['text-align', 'left']], ['left-sidebar--sticky-container js-sticky-leftnav', ['position', 'fixed']], ['mln12 mrn12 px12 py6 fl1 s-block-link', ['text-align', 'left']], ['mln12 mrn12 px12 py6 fl1 s-block-link', ['text-align', 'left']], ['mln12 mrn12 px12 py6 fl1 s-block-link', ['text-align', 'left']], ['mln12 mrn12 px12 py6 fl1 s-block-link', ['text-align', 'left']], ['s-block-link c-default fc-black-350 mln12 mrn12 px12 py6', ['text-align', 'left']], ['s-modal js-feed-link-modal', ['position', 'fixed']], ['ff-sans ps-fixed z-nav-fixed ws4 sm:w-auto p32 sm:p16 bg-black-750 fc-white bar-lg b16 l16 r16 js-consent-banner', ['position', 'fixed']]]
輸出包含具有來自目標規則集的樣式規則的所有元素的類名。
如果要獲取與每個樣式規則關聯的唯一類名,可以使用collections.defaultdict:
from collections import defaultdict
d = defaultdict(set)
for c_name, rule in classes:
d[tuple(rule)].add(c_name)
print({a:list(b) for a, b in d.items()})
輸出:
{('position', 'fixed'): ['left-sidebar--sticky-container js-sticky-leftnav', 's-modal js-feed-link-modal', 'ff-sans ps-fixed z-nav-fixed ws4 sm:w-auto p32 sm:p16 bg-black-750 fc-white bar-lg b16 l16 r16 js-consent-banner', 'top-bar js-top-bar top-bar__network'], ('text-align', 'left'): ['s-spinner s-spinner__sm fc-orange-400', 'mln12 mrn12 px12 py6 fl1 s-block-link', 'topbar-dialog siteSwitcher-dialog dno', 's-block-link c-default fc-black-350 mln12 mrn12 px12 py6', 'topbar-dialog leftnav-dialog js-leftnav-dialog dno', 'container']}
uj5u.com熱心網友回復:
Selenium 是一個非常好的自動化 Python 庫,但它允許使用 CSS 選擇器等進行網頁抓取和選擇多個。這應該允許您存盤所有元素
(“位置:固定;”在我的情況下)
使用硒,您將能夠提取資料,然后您可以隨意操作資料。決議資料本身的方法有很多,所以請在這部分更具體。如果有疑問,請將網站鏈接作為評論發送,并為您檢查 CSS 選擇器。希望這已經解決了這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/314426.html
下一篇:SoX統計選項的選擇性輸出?
