【问题标题】:Using BeautifulSoup to find links related to specific keyword使用 BeautifulSoup 查找与特定关键字相关的链接
【发布时间】: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 你是对的。谢谢

标签: python web-scraping beautifulsoup web-crawler


【解决方案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 传递给搜索匹配或子的标志参数。 stackoverflow.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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-01
      • 2018-10-30
      • 1970-01-01
      • 2011-12-05
      • 2022-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多