Использование BeautifulSoup для поиска ссылок, связанных с конкретным ключевым словом - PullRequest
0 голосов
/ 28 февраля 2019

Мне нужно изменить этот код, чтобы в нем содержались только ссылки, содержащие определенное ключевое слово.В моем случае я перебираю страницу газеты, чтобы найти новости, связанные с термином «Brexit».

example of target link

Я пытался изменить метод parse_links, поэтому он сохраняет только ссылки (или теги «a»), которые содержат в себе «Brexit», но, похоже, он не работает.

Куда поместить условие?

import requests
from bs4 import BeautifulSoup
from queue import Queue, Empty
from concurrent.futures import ThreadPoolExecutor
from urllib.parse import urljoin, urlparse

class MultiThreadScraper:

    def __init__(self, base_url):

        self.base_url = base_url
        self.root_url = '{}://{}'.format(urlparse(self.base_url).scheme, urlparse(self.base_url).netloc)
        self.pool = ThreadPoolExecutor(max_workers=20)
        self.scraped_pages = set([])
        self.to_crawl = Queue(10)
        self.to_crawl.put(self.base_url)

    def parse_links(self, html):
        soup = BeautifulSoup(html, 'html.parser')
        links = soup.find_all('a', href=True)
        for link in links:
            url = link['href']
            if url.startswith('/') or url.startswith(self.root_url):
                url = urljoin(self.root_url, url)
                if url not in self.scraped_pages:
                    self.to_crawl.put(url)

    def scrape_info(self, html):
        return

    def post_scrape_callback(self, res):
        result = res.result()
        if result and result.status_code == 200:
            self.parse_links(result.text)
            self.scrape_info(result.text)

    def scrape_page(self, url):
        try:
            res = requests.get(url, timeout=(3, 30))
            return res
        except requests.RequestException:
            return

    def run_scraper(self):
        while True:
            try:
                target_url = self.to_crawl.get(timeout=60)
                if target_url not in self.scraped_pages:
                    print("Scraping URL: {}".format(target_url))
                    self.scraped_pages.add(target_url)
                    job = self.pool.submit(self.scrape_page, target_url)
                    job.add_done_callback(self.post_scrape_callback)
            except Empty:
                return
            except Exception as e:
                print(e)
                continue
if __name__ == '__main__':
    s = MultiThreadScraper("https://elpais.com/")
    s.run_scraper()

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

Я добавил проверку в эту функцию.Посмотрите, поможет ли это вам:

def parse_links(self, html):
    soup = BeautifulSoup(html, 'html.parser')
    links = soup.find_all('a', href=True)
    for link in links:
        if 'BREXIT' in link.text.upper():  #<------ new if statement
            url = link['href']
            if url.startswith('/') or url.startswith(self.root_url):
                url = urljoin(self.root_url, url)
                if url not in self.scraped_pages:
                    self.to_crawl.put(url)
0 голосов
/ 28 февраля 2019

Вы можете получить текст элемента с помощью метода getText() и проверить, действительно ли строка содержит «Brexit»:

if "Brexit" in link.getText().split():
     url = link["href"]
0 голосов
/ 28 февраля 2019

Вам нужно импортировать re модуль, чтобы получить конкретное текстовое значение. Попробуйте следующий код.

import re
 links = soup.find_all('a', text=re.compile("Brexit"))

Это должно вернуть ссылки, которые содержат только Brexit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...