非常快速的网页抓取(Python)

时间:2013-11-24 01:23:26

标签: python screen-scraping

所以我试图过滤一个网址列表(可能是数百个)并过滤掉每个文章的正文少于X个单词(文章长度)。但是当我运行我的应用程序时,需要花费不合理的时间,以至于我的托管服务超时。我目前正在使用具有以下过滤功能的Goose(https://github.com/grangier/python-goose):

def is_news_and_data(url):
"""A function that returns a list of the form
    [True, title, meta_description]
    or
    [False]
"""
result = []
if url == None:
    return False
try:
    article = g.extract(url=url)
    if len(article.cleaned_text.split()) < ARTICLE_LENGTH:
        result.append(False)
    else:
        title = article.title
        meta_description = article.meta_description
        result.extend([True, title, meta_description])
except:
    result.append(False)
return result

在以下背景下。不介意调试打印和杂乱(tweepy是我的twitter api包装器):

def get_links(auth):
"""Returns a list of t.co links from a list of given tweets"""
api = tweepy.API(auth)
page_list = []
tweets_list = []
links_list = []
news_list = []
regex = re.compile('http://t.co/.[a-zA-Z0-9]*')

for page in tweepy.Cursor(api.home_timeline, count=20).pages(1):
    page_list.append(page)
for page in page_list:
    for status in page:
        tweet = status.text.encode('utf-8','ignore')
        tweets_list.append(tweet)

for tweet in tweets_list:
    links = regex.findall(tweet)
    links_list.extend(links)
#print 'The length of the links list is: ' + str(len(links_list))
for link in links_list:
    news_and_data = is_news_and_data(link)
    if True in news_and_data:
        news_and_data.append(link)
        #[True, title, meta_description, link]
        news_list.append(news_and_data[1:])
print 'The length of the news list is: ' + str(len(news_list))

有人可以推荐一种更快的方法吗?

2 个答案:

答案 0 :(得分:3)

此代码可能导致您的性能下降:

len(article.cleaned_text.split())

这正在执行大量工作,其中大部分都被丢弃了。我会分析你的代码,看看这是否是罪魁祸首,如果是这样,用一些只计算空格的东西替换它,就像这样:

article.cleaned_text.count(' ')

这不会给你与原始代码完全相同的结果,但会非常接近。为了更接近你可以使用正则表达式计算单词,但它不会那么快。

答案 1 :(得分:1)

我不是说这是你能做到的最绝对最好的,但它会更快。您将不得不重做一些代码以适应这个新功能。

它至少可以减少函数调用次数。

您必须传递整个网址列表。

def is_news_in_data(listings):
    new_listings = {}
    tmp_listing = ''
    is_news = {}
    for i in listings:
        url = listings[i]
        is_news[url] = 0
        article = g.extract(url=url).cleaned_text
        tmp_listing = '';
        for s in article:
            is_news[url] += 1
            tmp_listing += s
            if is_news[url] > ARTICLE_LENGTH:
                new_listings[url] = tmp_listing
                del is_news[url]
    return new_listings