iT邦幫忙

0

爬蟲: 排除特定文字底下的所有標籤

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

是使用BeautifulSoup和requests來抓取

在抓取時遇到一個問題,就是文章底下會出現"延伸閱讀"和底下的文字連結

但是該標籤的格式(屬性)在其他文章的內容中會出現,所以不能直接排除該標籤類型

如果排除的話,會讓其他文章抓出來的內容,可能會出現缺字的情形

https://ithelp.ithome.com.tw/upload/images/20210624/201194347a1mkMWThd.png
https://ithelp.ithome.com.tw/upload/images/20210624/20119434l9e4vHB7Lt.png

想請問有沒有方法可以排除特定文字(EX:延伸閱讀)底下所有的標籤?

程式碼:

import json
from bs4 import BeautifulSoup
import requests


class crawlerClass:
    def __init__(self):
        print("init")
        
    def udnCrawler(self, url):
        response = requests.get(url, verify=False)
        soup = BeautifulSoup(response.text, "html.parser")

        section = ""
        excepts = ['本文授權', '【文', '【尊重智慧財產權', '延伸閱讀', '【更多', '【2021']
        [s.extract()
         for s in soup.select('figcaption, p[style="margin-bottom: 0;"], li')]
        for tag in soup.select('div.article p, section.article-content__editor p, div.story_body_content p, div#story_body_content p'):
            # 去除空白tag
            if tag.get_text() != "":
                if sum([x in tag.get_text() for x in excepts]) != 0:
                    continue
                section += tag.get_text()
                # 去除換行或空格符號
                section = section.strip()
                section += "\n"
        article = {'status': 0, 'content': section}
        return json.dumps(article)  
        
if __name__ == "__main__":
    crawler = crawlerClass()
    # ==== udn ====
    url = "https://udn.com/news/story/6839/5516916"
    udnJsonStr = crawler.udnCrawler(url)
    udnContent = json.loads(udnJsonStr, encoding="utf-8")
    print("status:"+str(udnContent['status']))
    print(udnContent['content'])
反正問題也有了答案......

重點是還蠻多excepts關鍵字...用in還得要再for一次,偶個人比較懶,所以用 re.match(r"(a|b|c|d)")來玩
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
wrxue
iT邦好手 1 級 ‧ 2021-06-25 08:50:00
最佳解答

應該就判斷結尾到了沒,到了就不要迴圈就好了吧/images/emoticon/emoticon01.gif

endText = '延伸閱讀》'
for tag in soup.select('div.article p, section.article-content__editor p, div.story_body_content p, div#story_body_content p'):
    # 去除空白tag
    if tag.get_text() != "":
        print(endText, tag.get_text(), endText == tag.get_text())
        # 結尾到了就該結束了
        if endText in tag.get_text():
            break
        if sum([x in tag.get_text() for x in excepts]) != 0:
            continue
        section += tag.get_text()
        # 去除換行或空格符號
        section = section.strip()
        section += "\n"
聰明貓 iT邦新手 4 級 ‧ 2021-06-25 10:02:10 檢舉

哈哈! 早上同事也是這樣跟我說,說break不就好了...
好像問了個蠢問題XD
基礎真的還要再學好QQ

0
japhenchen
iT邦超人 1 級 ‧ 2021-06-25 09:56:35

用正則表達式檢查字串,以下用兩個判斷,一是符合就中斷for,一個是符合就不加入字串
content 我改成 list()

#以下基於你的原始程式碼加了一些 re 的判斷

import json
from bs4 import BeautifulSoup
import requests,re


class crawlerClass:
    def __init__(self):
        print("init")
        
    def udnCrawler(self, url):
        response = requests.get(url, verify=False)
        soup = BeautifulSoup(response.text, "html.parser")

        section = []
        title = ""

        NoContinue = ['本文授權', '【尊重智慧財產權', '延伸閱讀》', '【更多', '【2021']
        NoAppend = ["【文..*】"]
        reNoCont = re.compile(rf"({'|'.join(NoContinue)})")
        reNoAppend = re.compile(rf"({'|'.join(NoAppend)})")
        # 用list組成正則表達式過濾句
        # reNoCont 表示符合就不再繼續加入任何字串
        # reNoAppend 僅表示在符合條件下不加入本字串

        for t in soup.select(".article-content__title"):
            title = t.get_text()
        for tag in soup.select('.article-content__editor p'):
            tagtext=tag.get_text().strip()
            if tagtext!= "":              
                if reNoCont.match(tagtext):
                    break # 中斷 for
                if not reNoAppend.match(tagtext):
                    section.append(tagtext)
        article = {'status': 0,'title':title, "content": section}
        return json.dumps(article)  
        
if __name__ == "__main__":
    crawler = crawlerClass()
    # ==== udn ====
    url = "https://udn.com/news/story/6839/5516916"
    udnJsonStr = crawler.udnCrawler(url)
    udnContent = json.loads(udnJsonStr, encoding="utf-8")
    print("status:"+str(udnContent['status']))
    print("\n".join(udnContent["content"]))

輸出結果

status:0
通脹:美中角力第一回合!
我的好朋友中經合董事長Peter Liu,剛剛傳了一篇微信的文章給我,標題是:「報應來了,美國陷入嚴重通脹!」作者是
看到美國4月公布的CPI年增率達4.2%,作者認為美國將陷入惡性通貨膨脹的危機!我的看法正好相反,壓力在中國這一邊 
,而且,這很可能是美中角力雙方過招的第一回合。
大家看美國的通膨,我看克魯曼、葉倫都老神在在,甚至照克魯曼的說法,這一回美國是蓄意營造通膨。4月的美國CPI拉 
升至4.2%,這是相對去年最低的基期,這些年,美國印了大量鈔票,但都沒有達到通脹目標值2%的目標,這回借力使力, 
把壓力帶到中國這一邊!
最近中國領導人使盡全力壓制通膨,尤其是李克強,不過鐵礦砂等價格只是稍有回檔,但油價、銅價都在高檔,鋼價稍有 
拉回,但跌幅不大。在美國全力營造百年基礎建設及全球致力推動碳中和,原物料價格看起來易漲難跌,這是大趨勢,中 
國要壓抑原物料價格恐怕很困難。
中國過去卅年來以廉價工資,優越的生產力,為全球生產廉價產品,現在這個優勢走到盡頭,而共產黨領導最害怕通貨膨 
脹,這一回美國借力使力營造通膨,傷腦筋的是中國。
大家可能沒有太注意,4月中國的CPI是0.9%,但生產者物價指數(Ppi)是6.8%,如果大家把PPI及CPI過去卅年的走勢放在一
起比對一下,這是1990年以來開口最大的一次。
生產者物價上漲,一個是廠商反應成本,也跟著漲價,一個是廠商自行吸收,勢必影響獲利。現在這個情況是中央限令企 
業不能哄抬價格,廠商自行吸收原物料的價格,這是PPI 6.8%,CPI 0.9%的最核心原因。
企業漲不了價,很多低毛利的製造業紛紛裁員倒閉,最近這個現象也衝擊內循環的內需產業,例如,全中國最大的火鍋品 
牌海底撈,呷哺呷哺股價都腰斬。
為了平穩物價,這回人行放手讓人民幣升值,去年人民幣升值6%,今年又升至6.3左右,企業已大喊吃不消。這個情況跟台
灣1990年之前的新台幣升值很像!最近人行要求銀行要增加外匯部位,看起來似不願人民幣升更多。現在看來,通膨的問 
題在中國的身上。
過去卅年,中國扮演世界工廠角色,也輸出通縮,這回中國可能對全球輸出通脹,原物料價格的上漲可能是長期趨勢!   
看更多先前的回應...收起先前的回應...
聰明貓 iT邦新手 4 級 ‧ 2021-06-25 10:06:03 檢舉

感謝大大提供另一種解法
讓我可以學習到不同方式
發現您是正則表達式的愛好者XD

用正則表達式可以少做很多事,也可以減少誤判斷

我蠻常在youtube上爬音樂清單,就會用到正則來清理不必要的TAG,不然有時清單一多上千條,手動會起笑

聰明貓 iT邦新手 4 級 ‧ 2021-06-25 21:36:17 檢舉

哦哦 了解~

1
froce
iT邦大師 1 級 ‧ 2021-06-25 10:35:32

不要再直接用美麗的湯了...pyquery都直接用css selector了。

然後這種問題,我個人偏愛先找出要找的index,然後去做slice。

from requests_html import HTMLSession
session = HTMLSession()
r = session.get('https://udn.com/news/story/6839/5516916')

elms = r.html.find(".article-content__editor>p")
itemOfExclude = list(filter(lambda e: "延伸閱讀" in e.text, elms))
indexOfExclude = elms.index(itemOfExclude[0]) if len(itemOfExclude) > 0 else None
filtered = elms[slice(0, indexOfExclude)]
filteredText = [f.text for f in filtered if f.text != ""]
print("\n".join(filteredText))

結果:

【文.謝金河】
通脹:美中角力第一回合!
我的好朋友中經合董事長Peter Liu,剛剛傳了一篇微信的文章給我,標題是:「報應來了,美國陷入嚴重通脹!」作者是看到美國4月公布的CPI年增率達4.2%,作者認為美國將陷入惡性通貨膨脹的危機!我的看法正好相反,壓力在中國這一邊,而且,
這很可能是美中角力雙方過招的第一回合。
大家看美國的通膨,我看克魯曼、葉倫都老神在在,甚至照克魯曼的說法,這一回美國是蓄意營造通膨。4月的美國CPI拉升至4.2%,這是相對去年最低的基期,這些年,美國印了大量鈔票,但都沒有達到通脹目標值2%的目標,這回借力使力,把壓力帶 
到中國這一邊!
最近中國領導人使盡全力壓制通膨,尤其是李克強,不過鐵礦砂等價格只是稍有回檔,但油價、銅價都在高檔,鋼價稍有拉回,但跌幅不大。在美國全力營造百年基礎建設及全球致力推動碳中和,原物料價格看起來易漲難跌,這是大趨勢,中國要壓抑 
原物料價格恐怕很困難。
中國過去卅年來以廉價工資,優越的生產力,為全球生產廉價產品,現在這個優勢走到盡頭,而共產黨領導最害怕通貨膨脹,這一回美國借力使力營造通膨,傷腦筋的是中國。
大家可能沒有太注意,4月中國的CPI是0.9%,但生產者物價指數(Ppi)是6.8%,如果大家把PPI及CPI過去卅年的走勢放在一起比對一下,這是1990年以來開口最大的一次。
生產者物價上漲,一個是廠商反應成本,也跟著漲價,一個是廠商自行吸收,勢必影響獲利。現在這個情況是中央限令企業不能哄抬價格,廠商自行吸收原物料的價格,這是PPI 6.8%,CPI 0.9%的最核心原因。
企業漲不了價,很多低毛利的製造業紛紛裁員倒閉,最近這個現象也衝擊內循環的內需產業,例如,全中國最大的火鍋品牌海底撈,呷哺呷哺股價都腰斬。
為了平穩物價,這回人行放手讓人民幣升值,去年人民幣升值6%,今年又升至6.3左右,企業已大喊吃不消。這個情況跟台灣1990年之前的新台幣升值很像!最近人行要求銀行要增加外匯部位,看起來似不願人民幣升更多。現在看來,通膨的問題在中國
的身上。
過去卅年,中國扮演世界工廠角色,也輸出通縮,這回中國可能對全球輸出通脹,原物料價格的上漲可能是長期趨勢!
本文授權自今周刊,原文見此。
聰明貓 iT邦新手 4 級 ‧ 2021-06-25 21:38:14 檢舉

了解~ 感謝提供不同解法

我要發表回答

立即登入回答