首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用XPath和EasyList计算网页中的广告

用XPath和EasyList计算网页中的广告
EN

Code Review用户
提问于 2023-03-13 03:01:40
回答 1查看 46关注 0票数 1

我有以下函数,检索给定的网页,并使用EasyList的缩短版本(17,000条规则)返回页面上的广告数量。使用多处理,它在2天多一点的时间内就刮掉了18,000页(当时还不错)。但是,我现在有一个10倍大的数据集,所以这个运行时并不特别理想。由于for循环中的这一行result = len(document.xpath(rule)),我怀疑它是以二次形式运行的。

我对XPath/lxml一点也不熟悉,所以最好能给出一些关于如何提高效率的建议,或者至少说明一下我是否能让它运行得更快。

代码语言:javascript
复制
import lxml.html
import requests
import cssselect
import pandas as pd
from multiprocessing import Pool

def count_ads(url):

    rules_file = pd.read_csv("easylist_general_hide.csv", sep="\t",header=None)

    try:
        html = requests.get(url,timeout=5).text
    except:
        print(f"Page not found or timed out: {url}")
        return
    
    count = 0
    translator = cssselect.HTMLTranslator()

    for rule in rules_file[0]:
        try:
            rule = translator.css_to_xpath(rule[2:])
            document = lxml.html.document_fromstring(html)
            result = len(document.xpath(rule))
            if result>0:
                count = count+result
        except:
            pass

    return count```
EN

回答 1

Code Review用户

回答已采纳

发布于 2023-03-13 04:13:38

显然,您正在使用这个库:https://pypi.org/project/cssselect测量的处理刮过的页面的时间是10秒,我们希望减少这个时间。

OP中遗漏了许多重要的细节,包括对实际运行的轮廓仪观察。

我能看到至少有一件事可以立即得到改善。一个常数可以从循环中吊起。

代码语言:javascript
复制
        html = requests.get(url,timeout=5).text
        ...
    for rule in rules_file[0]:
        ...
            rule = translator.css_to_xpath(rule[2:])
            document = lxml.html.document_fromstring(html)
            result = len(document.xpath(rule))

看起来,常量的document解析可能会被提升,类似于translator已经被悬挂的方式。不需要重新计算它17K次,每条规则一次。

代码语言:javascript
复制
    document = lxml.html.document_fromstring(html)
    for rule in rules_file[0]:
        ...

假定给定的工作进程将处理多个URL。因此,对于N个页面,我们调用.css_to_xpath() 1.7e4×N次。看起来这里可能有一个缓存的机会。一种天真的方法只需在缓存装潢师上就行了:

代码语言:javascript
复制
@lru_cache(max_size=17_400)
def get_xpath(...):

但也可能有一些微妙的要求,比如所有的论点都是可以理解的。如果你遇到这样的麻烦,不要放弃。必须有一些方法来避免对相同的旧规则数据进行乏味的重复xpath提取。

一万七千条规则听起来挺多的。我敢打赌他们中的一些人经常触发,而有些人很少,也许是零次在你的语料库中。

你有时间和资源的限制。显然还不到20天。根据它们的有用程度排列顺序规则,并在您刚收到的页面上运行它们中的前一千条。公布初步结果。决定你是想回去尝试下一千条规则,还是一万条规则。

寻找模式。也许URL的主机名预测了最有可能应用于页面的100条规则。

这个计划有两个部分:

  1. I/O网页下载及
  2. 计算

前者的内存占用非常小,与后者不同。这对调度服务器资源有影响。

考虑打破一个只关注于发布.get()s (带有超时)的“获取”阶段,然后将结果持久化到磁盘。

然后,随后的“计算”阶段可以分析获取的页面,可能会在10秒钟内完成。

短期基准。

然后用pypy再试一次。有时候会赢的。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/283923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档