如何使用Python中的正则表达式从HTML <a>标签中提取Facebook页面URL?

3
我正在使用 Beautiful Soup 在 Python 3 中爬取一些网站,以提取 Facebook 页面的 URL。我只想提取每个网站的一个 URL,并将其重定向到 Facebook 页面配置文件,而不是共享类型页面。
因此,我尝试使用正则表达式从 `a` 标签的 `href` 属性中提取 URL。使用 Beautiful Soup,我提取了每个网站的第一个 `a` 标签,并通过包含 Facebook 页面 URL 的 `href` 属性值进行过滤。
我的代码如下:
# coding=utf-8
from bs4 import BeautifulSoup
import requests
import re


def makeSoup(website):
    if 'http' in website:
        page = requests.get(website)
    else:
        page = requests.get('http://' + website)
    soup = BeautifulSoup(page.content, 'html.parser')
    page.close()
    return soup


def facebookProfileScraper(soup):
    link = soup.find('a', {'href': re.compile("https?://(www\\.)?facebook\\.com/[^(share)]?(\\w+\\.?)+")})
    if link is None:
        return "NaN"
    return link['href'] 

以下是我希望提取URL的 <a> 标签示例(为了方便标识,我给每个网站都加上了数字,与我的尝试结果一样):
1. <a class="rss fb" href="http://www.facebook.com/gironafc" target="_blank">Facebook</a>
2. <a href="https://www.facebook.com/waterworld.parcaquatic" target="_blank"><i class="fa fa-facebook"></i></a>
3. <a class="social facebook" target="_blank" href="https://www.facebook.com/aquabrava"><span class="fa fa-facebook"></span></a>
4. <a href="https://www.facebook.com/UEO1921" target="_blank"><img alt="Facebook" height="32" src="http://www.ueolot.com/wp-content/themes/realsoccer/images/light/social-icon/facebook.png" width="32"/>
</a>
5. <a href="https://www.facebook.com/Roc%C3%B2drom-Girona-187271461378780/">Facebook</a>
6. <a class="fb_share" href="https://www.facebook.com/pages/Skydive-Empuriabrava/44214266003?fref=ts" target="_blank"></a>

第一次尝试

https?://(www\\.)?facebook\\.com/[^(share)]?(\\w+\\.?)+

但我得到了这些 </a> 标签:
1. <a href="http://facebook.com/share.php?src=bm&amp;v=3&amp;u=" target="_blank"><span class="fa fa-facebook"></span></a>
2. <a href="https://www.facebook.com/waterworld.parcaquatic" target="_blank"><i class="fa fa-facebook"></i></a>
3. <a class="social facebook" href="https://www.facebook.com/aquabrava" target="_blank"><span class="fa fa-facebook"></span></a>
4. <a href="https://www.facebook.com/UEO1921" target="_blank"><img alt="Facebook" height="32" src="http://www.ueolot.com/wp-content/themes/realsoccer/images/light/social-icon/facebook.png" width="32"/>
</a>
5. <a href="https://www.facebook.com/Roc%C3%B2drom-Girona-187271461378780/">Facebook</a>
6. <a class="fb_share" href="https://www.facebook.com/pages/Skydive-Empuriabrava/44214266003?fref=ts" target="_blank"></a>

我从网站1获取了错误的<a>标签。

第二次尝试

https?://(www\\.)?facebook\\.com/[^(share)](\\w+\\.?)+

我尝试删除 [^share] 后面的 ?,但我得到了以下标签:

1. <a class="rss fb" href="http://www.facebook.com/gironafc" target="_blank">Facebook</a>
2. <a href="https://www.facebook.com/waterworld.parcaquatic" target="_blank"><i class="fa fa-facebook"></i></a>
3. None
4. <a href="https://www.facebook.com/UEO1921" target="_blank"><img alt="Facebook" height="32" src="http://www.ueolot.com/wp-content/themes/realsoccer/images/light/social-icon/facebook.png" width="32"/>
</a>
5. <a href="https://www.facebook.com/Roc%C3%B2drom-Girona-187271461378780/">Facebook</a>
6.<a class="fb_share" href="https://www.facebook.com/pages/Skydive-Empuriabrava/44214266003?fref=ts" target="_blank"></a>

来自网站3。我不提取任何<a>标签,因为通过[^(share)]我否定了在http://www.facebook.com/之后具有a(或任何一个shre)的任何url。

第三次尝试

https?://(www\\.)?facebook\\.com/(\\w+\\.?)+

我尝试删除 [^share],但得到的标签与第一次尝试时相同,因此也获取了分享类型的 URL。

如何仅选择没有分享类型 Facebook URL 作为 href 值的 a 标签?


1
所以你想从一个没有分享的Facebook页面中提取URL,是吗? - Yashik
确切地说!我编辑了文本,使其更加清晰。 - silviacamplani
3个回答

3
def foo(url):
    l = []
    soup = BeautifulSoup(requests.get(url).text, "html.parser")
    links = soup.find_all("a")
    for link in links:
        if not "share" in link.get("href").lower():
            l.append(link)
    return l

此函数检查链接中是否包含 share,并返回不包含 share 的链接。


谢谢!这个解决方案可行,但我更希望正则表达式的解决方案能够提高我的代码性能 :) - silviacamplani

2

我通过改进正则表达式找到了解决方案。 这个问题对我帮助很大。 以下是适用于我的情况的正则表达式:

^(?!.*(word1|word2)).*$ 其中,"word1"和"word2"是你想要排除的单词。
https?://(www\.)?facebook\.com/(?!share\.php).(\S+\.?)+

它匹配所有 <a> 标签中的 Facebook 页面链接作为 href 值。

使用正则表达式 (?!anywordorexpression). 将不会提取包含 anywordorexpression 子字符串的任何字符串。

最初的回答已经涵盖了所有需要翻译的内容。


1
你可以使用bs4 4.7.1版本的:not和* contains运算符来使用更有效的css属性选择器。
links = [item['href'] for item in soup.select("[href^='https://www.facebook.com/']:not([href*='share'])")]

仅针对第一个链接。
link = soup.select_one("[href^='https://www.facebook.com/']:not([href*='share'])")['href']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接