iT邦幫忙

0

爬蟲: 使用排除標籤的語法,執行結果和預期不符

目前在抓取泛新聞裡面完整的內容

是使用BeautifulSoup和requests來抓取

在排除標籤時遇到一個問題,就是將目標tag中,第一個或最後一個標籤排除時

會連帶影響到其他原本正常選取的標籤

舉例來說,新聞內容都放在<div> class="post-content-container"底下的<p>裡面

標題文字都放在<h2>底下的<strong>裡面
https://ithelp.ithome.com.tw/upload/images/20210531/20119434PxyWoT9KpN.png
https://ithelp.ithome.com.tw/upload/images/20210531/20119434ZfekMNOdtk.png

前面有特殊符號的文字都放在<ul>底下的<li>裡面
https://ithelp.ithome.com.tw/upload/images/20210531/20119434cH6yzJ8ptx.png
https://ithelp.ithome.com.tw/upload/images/20210531/20119434j1hRgpDrDi.png

因為標題文字<strong>中最後一個標籤的內容 "延伸閱讀" 不是文章內容,所以要排除
https://ithelp.ithome.com.tw/upload/images/20210531/20119434xjUUimdB4V.png

使用 :not(:last-of-type) 或 :not(:nth-last-child) 排除最後一個標籤的語法
section#firstSingle div.post-content-container h2 strong:not(:last-of-type)

除了最後一個標籤的內容不見,中間原本抓出的標題也會不見
原:
https://ithelp.ithome.com.tw/upload/images/20210531/20119434Ni4Ea5naih.png
https://ithelp.ithome.com.tw/upload/images/20210531/20119434a0UXN5bEgY.png
使用後:
https://ithelp.ithome.com.tw/upload/images/20210531/20119434GyqqIprhqg.png
https://ithelp.ithome.com.tw/upload/images/20210531/20119434sB4bqINsDH.png

同理,使用 :not(:first-of-type) 或 :not(:nth-first-child) 排除第一個標籤的語法
section#firstSingle div.post-content-container ul li:not(:first-of-type)

將前面含特殊符號文字<li>第一個標籤的內容 "蔣維倫 / 泛科學 PanSci 專欄作家..."

作者介紹給排除,中間會少抓一個tag的內容
原:
https://ithelp.ithome.com.tw/upload/images/20210531/20119434Oww8NPLOIj.png
https://ithelp.ithome.com.tw/upload/images/20210531/20119434gYCuhUR8vr.png
使用後:
https://ithelp.ithome.com.tw/upload/images/20210531/201194341yf8AfDHUP.png
https://ithelp.ithome.com.tw/upload/images/20210531/20119434gzwf1ZJNFG.png

有人知道是什麼原因嗎? 該怎麼解決?

程式碼:

import json
from bs4 import BeautifulSoup
import requests


class crawlerClass:
    def __init__(self):
        print("init")
    def PansciCrawler(self, url):
        response = requests.get(url, verify=False)
        soup = BeautifulSoup(response.text, "html.parser")
        section = ""
        # p文章內容,h2 strong標題文字,ul li前面含特殊符號文字
        for tag in soup.select('section#firstSingle div.post-content-container p:not(:nth-last-child(4)), section#firstSingle div.post-content-container h2 strong, section#firstSingle div.post-content-container ul li'):
            children = tag.findChild()
            if children == None:
                if tag.get_text() != "":
                    section += tag.get_text()
                    section += "\n\n"
        article = {'status': 0, 'content': section}
        return json.dumps(article)


if __name__ == "__main__":
    crawler = crawlerClass()
    # ==== Pansci ====
    url = "https://pansci.asia/archives/320488"
    pansciJsonStr = crawler.PansciCrawler(url)
    pansciContent = json.loads(pansciJsonStr, encoding="utf-8")
    print("status:"+str(pansciContent['status']))
    print(pansciContent['content'])

1 個回答

0
wrxue
iT邦研究生 3 級 ‧ 2021-05-31 19:25:19
最佳解答
section#firstSingle div.post-content-container h2 strong:not(:last-of-type)

應該為

section#firstSingle div.post-content-container h2:not(:last-of-type) strong

section#firstSingle div.post-content-container ul li:not(:first-of-type)

應該為

section#firstSingle div.post-content-container ul:not(:first-of-type) li

可以發現你的 pseudo class 都放錯地方,可以趁這個機會好好的了解一下 pseudo class。

好的,謝謝~

應該是這篇裡面介紹的
https://ithelp.ithome.com.tw/articles/10218197
貼上來給其他有困惑的小夥伴了解

我要發表回答

立即登入回答