Python: Newspaper Module - Есть ли способ объединить получение статей прямо с URL?
Я использую модуль Newspaper для Python, найденный здесь.
В руководствах описывается, как вы можете объединить здание из разных газет, если оно генерирует их одновременно. (см. "Загрузка многопоточной статьи" в ссылке выше)
Есть ли способ сделать это для извлечения статей прямо из списка URL-адресов? То есть есть ли какой-нибудь способ, которым я могу добавить несколько URL-адресов в следующую настройку, чтобы она загружалась и анализировала их одновременно?
from newspaper import Article
url = 'http://www.bbc.co.uk/zhongwen/simp/chinese_news/2012/12/121210_hongkong_politics.shtml'
a = Article(url, language='zh') # Chinese
a.download()
a.parse()
print(a.text[:150])
3 ответа
Я смог сделать это, создав Source
для каждой статьи URL. (отказ от ответственности: не разработчик Python)
import newspaper
urls = [
'http://www.baltimorenews.net/index.php/sid/234363921',
'http://www.baltimorenews.net/index.php/sid/234323971',
'http://www.atlantanews.net/index.php/sid/234323891',
'http://www.wpbf.com/news/funeral-held-for-gabby-desouza/33874572',
]
class SingleSource(newspaper.Source):
def __init__(self, articleURL):
super(StubSource, self).__init__("http://localhost")
self.articles = [newspaper.Article(url=url)]
sources = [SingleSource(articleURL=u) for u in urls]
newspaper.news_pool.set(sources)
newspaper.news_pool.join()
for s in sources:
print s.articles[0].html
Я знаю, что этот вопрос действительно старый, но это одна из первых ссылок, которая появляется, когда я гуглю, как получить многопоточную газету. Хотя ответ Кайлса очень полезен, он неполон, и я думаю, что в нем есть некоторые опечатки...
import newspaper
urls = [
'http://www.baltimorenews.net/index.php/sid/234363921',
'http://www.baltimorenews.net/index.php/sid/234323971',
'http://www.atlantanews.net/index.php/sid/234323891',
'http://www.wpbf.com/news/funeral-held-for-gabby-desouza/33874572',
]
class SingleSource(newspaper.Source):
def __init__(self, articleURL):
super(SingleSource, self).__init__("http://localhost")
self.articles = [newspaper.Article(url=articleURL)]
sources = [SingleSource(articleURL=u) for u in urls]
newspaper.news_pool.set(sources)
newspaper.news_pool.join()
Я изменил Stubsource на Singlesource и один из URL-адресов на articleURL. Конечно, это просто загружает веб-страницы, вам все еще нужно разобрать их, чтобы иметь возможность получить текст.
multi=[]
i=0
for s in sources:
i+=1
try:
(s.articles[0]).parse()
txt = (s.articles[0]).text
multi.append(txt)
except:
pass
В моей выборке из 100 URL это заняло половину времени по сравнению с последовательной работой с каждым URL. (Изменить: после увеличения размера выборки до 2000, происходит сокращение примерно на четверть.)
(Правка: все работает с многопоточностью!) Я использовал это очень хорошее объяснение для своей реализации. При размере выборки в 100 URL-адресов использование 4 потоков занимает время, сопоставимое с кодом выше, но увеличение числа потоков до 10 дает дальнейшее сокращение примерно вдвое. Больший размер выборки требует большего количества потоков, чтобы дать сопоставимую разницу.
import newspaper
from multiprocessing.dummy import Pool as ThreadPool
def getTxt(url):
article = Article(url)
article.download()
try:
article.parse()
txt=article.text
return txt
except:
return ""
pool = ThreadPool(10)
# open the urls in their own threads
# and return the results
results = pool.map(getTxt, urls)
# close the pool and wait for the work to finish
pool.close()
pool.join()
Опираясь на ответ Джозефа Валлса. Я предполагаю, что исходный плакат хотел использовать многопоточность для извлечения кучи данных и их правильного хранения. После долгих попыток я думаю, что нашел решение, оно может быть не самым эффективным, но оно работает, однако я попытался сделать его лучше, я думаю, что плагин газета3k может быть немного глючным. Однако это работает при извлечении желаемых элементов в DataFrame.
import newspaper
from newspaper import Article
from newspaper import Source
import pandas as pd
gamespot_paper = newspaper.build('https://www.gamespot.com/news/', memoize_articles=False)
bbc_paper = newspaper.build("https://www.bbc.com/news", memoize_articles=False)
papers = [gamespot_paper, bbc_paper]
news_pool.set(papers, threads_per_source=4)
news_pool.join()
#Create our final dataframe
df_articles = pd.DataFrame()
#Create a download limit per sources
limit = 100
for source in papers:
#tempoary lists to store each element we want to extract
list_title = []
list_text = []
list_source =[]
count = 0
for article_extract in source.articles:
article_extract.parse()
if count > limit:
break
#appending the elements we want to extract
list_title.append(article_extract.title)
list_text.append(article_extract.text)
list_source.append(article_extract.source_url)
#Update count
count +=1
df_temp = pd.DataFrame({'Title': list_title, 'Text': list_text, 'Source': list_source})
#Append to the final DataFrame
df_articles = df_articles.append(df_temp, ignore_index = True)
print('source extracted')
Пожалуйста, предлагайте какие-либо улучшения!
Я не знаком с модулем "Газета", но следующий код использует список URL-адресов и должен быть эквивалентен тому, который представлен на связанной странице:
import newspaper
from newspaper import news_pool
urls = ['http://slate.com','http://techcrunch.com','http://espn.com']
papers = [newspaper.build(i) for i in urls]
news_pool.set(papers, threads_per_source=2)
news_pool.join()