使用 BeautifulSoup 查找与特定关键字相关的链接

Posted

技术标签:

【中文标题】使用 BeautifulSoup 查找与特定关键字相关的链接【英文标题】:Using BeautifulSoup to find links related to specific keyword 【发布时间】:2019-07-22 10:06:47 【问题描述】:

我必须修改这段代码,以便 scraping 只保留包含特定关键字的链接。就我而言,我正在抓取报纸页面来查找与“Brexit”一词相关的新闻。

我尝试修改 parse_links 方法,使其仅保留包含“Brexit”的链接(或“a”标签),但似乎不起作用。

我应该把条件放在哪里?

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()

【问题讨论】:

listkeywords 怎么样,并检查它是否存在于锚标记的文本中? @user5173426 我尝试检查链接中是否存在所需的单词。在检查链接中的每个链接之前,但没有得到任何结果 记得在edit 中通过sn-p 工具插入html 而不是图像。希望您的问题得到应得的支持 + @QHarr 你是对的。谢谢 【参考方案1】:

您可以使用方法getText() 获取元素的文本并检查字符串是否实际包含“Brexit”:

if "Brexit" in link.getText().split():
     url = link["href"]

【讨论】:

【参考方案2】:

你需要导入re模块来获取具体的文本值。试试下面的代码。

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

这应该返回仅包含英国退欧的链接。

【讨论】:

@Kajal,我只是好奇,如果文本中的“brexit”全部小写,这是否也有效?换句话说,使用re.compile("Brexit") 会区分大小写吗? re.compile() 区分大小写。但是你可以在 re.compile() 中添加 re.IGNORECASE。 @chitown88 您可以将 re.IGNORECASE 传递给搜索匹配或子的标志参数。 ***.com/questions/500864/… 哦,太好了。我必须记住这一点。感谢 Kajal 和 Carlos,这对我将来很有用。 您可以使用 range(len(links)) 并循环遍历它,并在达到 20 时使用 break 检查从循环中跳出。【参考方案3】:

我在这个函数中添加了一个检查。看看这是否对你有用:

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)

【讨论】:

以上是关于使用 BeautifulSoup 查找与特定关键字相关的链接的主要内容,如果未能解决你的问题,请参考以下文章

使用 BeautifulSoup 查找具有两种特定样式的标签

使用 BeautifulSoup 查找包含特定文本的 HTML 标签

BeautifulSoup/Regex:从 href 中查找特定值

查找带有 beautifulsoup 的特定链接

python/beautifulsoup 查找所有带有特定锚文本的 <a href>

使用 Beautiful Soup 查找特定类