【问题标题】:Python requests and BeautifulSoup4 .get('href') returning absolute address when scraping from Safaribooksonline从 Safaribooksonline 抓取时,Python 请求和 BeautifulSoup4 .get('href') 返回绝对地址
【发布时间】:2018-03-13 08:21:46
【问题描述】:

我正在尝试从网页中抓取 <a> 标记的内容。我的代码是:

from bs4 import BeautifulSoup
import requests
import sys

reload(sys)
sys.setdefaultencoding('utf-8')

url = 'https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961'

req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')

lessons = soup.find_all('li', class_='toc-level-1')
lesson = lessons[0]
print(lesson)

我的页面有一个元素:(直接从我在 Firefox 中的 DOM 检查器的输出中获得)...

<li class="toc-level-1 t-toc-level-1 js-content-uri" data-content-uri="/api/v1/book/9780134985961/chapter/LPOC_00_00_00.html">
   <a href="/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html" class="t-chapter" tabindex="39">Introduction</a>
   <ol>
      <li class="toc-level-2 t-toc-level-2 js-content-uri" data-content-uri="/api/v1/book/9780134985961/chapter/LPOC_00_00_00.html"><a href="/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html" class="t-chapter" tabindex="41">Linux Performance Optimization: Introduction</a></li>
   </ol>
</li>

但是,当我使用 requests 和 bs4 模块来抓取数据时,使用上面的代码,我得到的输出是:

<li class="toc-level-1 t-toc-level-1">
    <a class="t-chapter js-chapter" href="https://www.safaribooksonline.comhttps://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html">Introduction</a>
    <ol>
        <li class="toc-level-2 t-toc-level-2">
            <a class="t-chapter js-chapter" href="https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html">Linux Performance Optimization: Introduction</a>
        </li>
    </ol>
</li>

注意到&lt;a&gt; 标签的href 值了吗?它们应该是相对 URL,例如:/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html,但我得到的是绝对 URL——有时这太错误了:https://www.safaribooksonline.comhttps://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html

我不知道域名是如何作为链接 url 的前缀的,因为在原始 HTML 中只给出了 href 值,除非 requests 或 bs4 这样做。我以前使用相同方法的所有脚本也产生了类似的错误。模块方面是否发生了变化,还是我做错了什么?

【问题讨论】:

  • @Rahul 惊人的洞察力,我刚才描述的内容来自我在 Firefox 中的源代码查看器的输出。网络控制台。所以,这就是我的浏览器正在处理的内容。这就是我想知道requests 模块、bs4 或我的代码是否有问题的原因。另外,也许下次在调用 rubbish 之前,请尝试自己验证问题是否存在?哦,他们被称为absolute urls,伙计,不是完整的网址,并且没有网站内部链接使用这些链接,因为如果域更改它们会中断。
  • 好的天才。祝你好运。因为您的信息源不会将浏览器更改为浏览器。我检查了chrome和firefox。来源有完整的网址。 bs4 不会改变任何东西。它只是解析。可能是早期网站有不同的酸味。
  • 我刚刚使用wget 进行了检查,HTML 源代码的第 335 行确实是 ` safaribooksonline.comhttps://www.safaribooksonline.com/library/…" class="t-chapter js-chapter">I .` -问题出在 safaribooksonline.com 网站上,而不是您的代码、bs4 和请求。此外,本网站上的大多数 URL 都是绝对的。我见过一些相对 URL,但不是太多。
  • @ElmoVanKielmo 好的,所以有人可能破坏了他们的 URL?那个链接失效了!至于使用的链接类型 - 当然,取决于开发人员。但我确信 safaribooksonline 使用相对链接是因为the output of my DOM inspector
  • 这个网站 safaribooksonline.com 非常不一致 - 我并不是说您的屏幕截图中的链接具有绝对 URL。但是这个网站上的大多数 URL 都是绝对的。

标签: python web-scraping beautifulsoup python-requests


【解决方案1】:

您可以使用正则表达式从href 中提取 URL:

from bs4 import BeautifulSoup
import requests
import sys
import re

url = 'https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961'

req = requests.get(url)
soup = BeautifulSoup(req.text, 'html.parser')
hrefs = set()

for lesson in soup.find_all('li', class_='toc-level-1'):
    for a in lesson.find_all('a', href=True):
        found_urls = re.split(r'(https?:\/\/.*?)', a['href'])
        hrefs.add(found_urls[-2] + found_urls[-1])

for href in sorted(hrefs):
    print(href)

给你一个找到的href列表开始:

https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_00_00_00.html
https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_01_00_00.html
https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_01_01_00.html
https://www.safaribooksonline.com/library/view/linux-performance-optimization/9780134985961/LPOC_01_01_01.html

【讨论】:

  • 非常接近我所做的......实际上让验证器从错误的源代码中过滤掉由 BS4 生成的格式错误的 URL!
猜你喜欢
  • 2020-06-01
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多