本文仅讨论核心代码的技术实现思路,以及从代码中看出来的一些内容,涉及到的内容基本包含以下四个文件
- rumEventCollection
- actionCollection
- getActionNameFromElement
- listenActionEvents
- trackClickAction
以下内容,方便用户了解,我做了一些整理,包括精华代码部分。
监听
事件获取的前提第一步是监听,有关click事件,比较简单,就不在本文进行讨论:
var listeners = [ addEventListener(),]
根据监听的事件,就要考虑监听哪些事件,除了click事件,还有:
- POINTER_DOWN
- SELECTION_CHANGE
- POINTER_UP
- INPUT
其中addEventListener的入参有几项:
- eventTarget,也就是dom元素
- event,也就是事件
- listener
- options
其中代码逻辑如下,我们看到还是回归到了添加监听事件后的处理上,
export function addEventListener(eventTarget, event, listener, options) {
return addEventListeners(eventTarget, [event], listener, options)
}
事件处理
其中有关addEventListeners服务器托管网,首先是非空验证isSelectionEmpty(),其次就是事件处理代码,分别是:
- onPointerDown—->processPointerDown
- userActivity.selection = true
- onPointerUp—->startClickAction
- userActivity.input = true
看到这里基本事件处理就结束了。
事件名称
接下来是事件名称的获取,这里也不讨论兼容性等,目前主要的方法是getActionNameFromElement。这个方法主要有以下两个内容点:
- getActionNameFromElementProgrammatically
- getActionNameFromElementForStrategies
这样分的考虑在于是否能直接从元素中获取actionName:第一个是能直接从元素中获取actionName,第二个是不能直接从元素中获取actionName。
直接获取actionName
因为dom元素和嵌套的方式是千奇百怪的,所以这里需要考虑元素和元素的parent。
getActionNameFromElementProgrammatically(
element,
DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE
) ||
(userProgrammaticAttribute &&
getActionNameFromElementProgrammatically(
element,
userProgrammaticAttribute
)) ||
getActionNameFromElementForStrategies(
element,
userProgrammaticAttribute,
priorityStrategies
) ||
getActionNameFromElementForStrategies(
element,
userProgrammaticAttribute,
fallbackStrategies
) ||
''
)
有关元素中哪些属性是直接从element中获取的呢?基本都能数出来,所以这里就不赘述了。
不能直接获取actionName
function getActionNameFromElementForStrategies(
targetElement,
userProgrammaticAttribute,
strategies
) {
var element = targetElement
var recursionCounter = 0
while (
recursionCounter
其中最后一个参数 策略 ,这里有两点:
- priorityStrategies
- fallbackStrategies
这里只有针对的拿出几个点来说明,非button类,可能获取哪些内容:
- alt
- name
- title
- palceholder在上述策略中,兜底的是纯文本内容,该如何获取:
function getTextualContent(element, userProgrammaticAttribute) {
if (element.isContentEditable) {
return
}
if ('innerText' in element) {
var text = element.innerText
var removeTextFromElements = function (query) {
var list = element.querySelectorAll(query)
for (var index = 0; index 0) {
text = text.replace(textToReplace, '')
}
}
}
}
if (!supportsInnerTextScriptAndStyleRemoval()) {
// remove the inner text of SCRIPT and STYLES from the result. This is a bit dirty, but should
// be relatively fast and work in most cases.
removeTextFromElements('script, style')
}
// remove服务器托管网 the text of elements with programmatic attribute value
removeTextFromElements(
'[' + DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE + ']'
)
if (userProgrammaticAttribute) {
removeTextFromElements('[' + userProgrammaticAttribute + ']')
}
return text
}
return element.textContent
}
到这里基本核心代码都覆盖到了,仅仅有一些小点,比如事件报错、元素判断,因为篇幅,就不在本文介绍,不过相关代码还是可以看看的,比如
判断事件
function isValidPointerEvent(event) {
return (
event.target instanceof Element &&
// Only consider 'primary' pointer events for now. Multi-touch support could be implemented in
// the future.
event.isPrimary !== false
)
}
获取事件名称中,循环遍历父亲节点时的终止条件:
while (
recursionCounter
当然,本文没有讲到自定义事件的收集,这部分比较简单,我把代码粘贴出来,就不做讨论了。
addAction: function (name, context) {
addActionStrategy({
name: name,
context: deepClone(context),
startClocks: clocksNow(),
type: ActionType.CUSTOM
})
},
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
随着互联网的发展,数据已经成为一种非常重要的资源。因此,大规模数据抓取已经成为了很多公司和组织的常见需求。在这个过程中,爬虫技术无疑是一个非常强大的工具,而Go语言作为一门高效的编程语言,也被广泛应用于爬虫程序的开发中。本文将探讨Go爬虫在大规模数据抓取中的性…