Python веб-соскоб из списка URL-адресов - PullRequest
1 голос
/ 07 июня 2019

Я новичок в аске и трио в питоне, я получил пример кода.позвольте мне объяснить, что у меня есть список URL-адресов, каждый из которых является новостным URL-адресом, у каждого есть под-URL.первый запрос URL и получить все другие ссылки и добавить в список.затем получите статью всех ссылок в этом списке.Проблема заключается в том, что иногда статьи становятся пустыми.

пробовал пример кода для отдельных URL-адресов, на этот раз он работал

import asks
import trio
from goose3 import Goose
import logging as log
from goose3.configuration import ArticleContextPattern
from pprint import pprint
import json
import time

asks.init('trio') 


async def extractor(path, htmls, paths, session):

    try:
        r = await session.get(path, timeout=2)
        out = r.content
        htmls.append(out)
        paths.append(path)
    except Exception as e:
        out = str(e)
        htmls.append(out)
        paths.append(path)


async def main(path_list, session):    
    htmls = []
    paths = []
    async with trio.open_nursery() as n:
        for path in path_list:
            n.start_soon(extractor, path, htmls, paths, session)

    return htmls, paths


async def run(urls, conns=50): 


    s = asks.Session(connections=conns)
    g = Goose()

    htmls, paths = await main(urls, s)
    print(htmls,"       ",paths)
    cleaned = []
    for html, path in zip(htmls, paths):
        dic = {}
        dic['url'] = path
        if html is not None:                            
            try:
                #g.config.known_context_pattern = ArticleContextPattern(attr='class', value='the-post')
                article = g.extract(raw_html=html)
                author=article.authors
                dic['goose_text'] = article.cleaned_text
                #print(article.cleaned_text)
                #dic['goose_date'] = article.publish_datetime
                dic['goose_title'] = article.title
                if author:
                    dic['authors']=author[0]
                else:
                    dic['authors'] =''
            except Exception as e:
                raise
                print(e)
                log.info('goose found no text using html')
                dic['goose_html'] = html
                dic['goose_text'] = ''
                dic['goose_date'] = None
                dic['goose_title'] = None
                dic['authors'] =''
            cleaned.append(dic)
    return cleaned




async def real_main():
    sss= '[{"crawl_delay_sec": 0, "name": "mining","goose_text":"","article_date":"","title":"", "story_url": "http://www.mining.com/canalaska-start-drilling-west-mcarthur-uranium-project","url": "http://www.mining.com/tag/latin-america/page/1/"},{"crawl_delay_sec": 0, "name": "mining", "story_url": "http://www.mining.com/web/tesla-fires-sound-alarms-safety-electric-car-batteries", "url": "http://www.mining.com/tag/latin-america/page/1/"}]'

    obj = json.loads(sss)
    pprint(obj)

    articles=[]
    for l in obj:
      articles.append(await run([l['story_url']]))
      #await trio.sleep(3)

    pprint(articles)

if __name__ == "__main__":
    trio.run(real_main)

получить данные статьи без пропусков

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

«спрашивает» не всегда вызывает исключение, когда код состояния равен! = 200. Необходимо проверить код статуса ответа перед использованием его содержимого. Возможно, вы также захотите увеличить время ожидания, 2 секунд недостаточно, особенно если вы запускаете до 50 параллельных соединений.

В любом случае, вот упрощенная программа - все эти вещи Goose совершенно не нужны для отображения фактической ошибки, два массива результатов не очень хорошая идея, и добавление сообщений об ошибках в массив результатов выглядит неработоспособным.

Также вам следует изучить параллельный запуск извлечения и обработки URL. trio.open_memory_channel твой друг здесь.


import asks
asks.init('trio')

import trio
from pprint import pprint

async def extractor(path, session, results):
    try:
        r = await session.get(path, timeout=2)
        if r.status_code != 200:
            raise asks.errors.BadStatus("Not OK",r.status_code)
        out = r.content
    except Exception as e:
        # do some reasonable error handling
        print(path, repr(e))
    else:
        results.append((out, path))

async def main(path_list, session):
    results = []
    async with trio.open_nursery() as n:
        for path in path_list:
            n.start_soon(extractor, path, session, results)
    return results


async def run(conns=50):
    s = asks.Session(connections=conns)

    urls = [
            "http://www.mining.com/web/tesla-fires-sound-alarms-safety-electric-car-batteries",
            "http://www.mining.com/canalaska-start-drilling-west-mcarthur-uranium-project",
            "https://www.google.com",  # just for testing more parallel connections
            "https://www.debian.org",
            ]

    results = await main(urls, s)
    for content, path in results:
        pass  # analyze this result
    print("OK")

if __name__ == "__main__":
    trio.run(run)
0 голосов
/ 07 июня 2019

Мне не хватает какой-то дополнительной информации, чтобы подробно ответить на ваш вопрос, но, скорее всего, это связано с тем, как гусиные слова ищут текст в html.Смотрите этот ответ для более подробной информации: https://stackoverflow.com/a/30408761/8867146

...