iT邦幫忙

0

爬蟲時遇到不是編碼原因的亂碼

在爬取一個網站時
遇到這個亂碼
網頁原始碼的部分

<span style="display:none">亂碼</span>要爬取的部分<br />

不管怎麼改標籤
都沒辦法避開亂碼的部分
有什麼方法嗎?

import requests
from bs4 import BeautifulSoup
def ourl(url):
    res=requests.get(url)
    res.encoding='big5'
    soup=BeautifulSoup(res.text,'html.parser')
    return soup
url='http://ds-hk.net/thread-93278-1-49.html'
soup=ourl(url)
print(soup.select('.t_msgfont')[0])
看更多先前的討論...收起先前的討論...
listennn08 iT邦研究生 3 級 ‧ 2020-05-28 17:30:14 檢舉
error log 跟亂碼在哪?
dragonH iT邦超人 6 級 ‧ 2020-05-28 17:32:10 檢舉
我也想問這個
我只想問,為何要宣告big5??
s4028600 iT邦新手 5 級 ‧ 2020-05-28 18:20:28 檢舉
@listennn08 現在才發現被隱藏了 我顯示出來了
@浩瀚星空 因為不宣告會出現編碼亂碼
好像故意加了很多亂碼在文章中
listennn08 iT邦研究生 3 級 ‧ 2020-05-28 21:39:53 檢舉
我爬完跟點網頁進去比較如下
網頁 => ( M# Y: q" p' S7 B3 rbl,gl.comic,music,同人誌,耽美,論壇,小說,會員,免費,註冊,討論區,星座,文字,貼圖,心理測驗,笑話,潮流,詩詞,BL,電玩,原創,散文,文章,版主,壇主,資源
python => 4 y; J3 t2 L- Jbl,gl.comic,music,同人誌,
耽美,論壇,小說,會員,免費,註冊,討論區,星座,文字,貼圖,心理測驗,笑話,潮流,詩詞,BL,下載,電玩,原創,散文,文章,版主,壇主,資源
要避開亂碼就抓你要的地方再 encoding 不是比較好嗎
dragonH iT邦超人 6 級 ‧ 2020-05-28 21:58:33 檢舉
那網頁 charset 用 big5
s4028600 iT邦新手 5 級 ‧ 2020-05-28 22:22:43 檢舉
@listennn08 問題是沒辦法只抓要的地方...
encoding是指網頁編碼?我用big5解決了
淺水員 iT邦新手 1 級 ‧ 2020-05-29 00:34:17 檢舉
抓這個網站的內容要過濾掉一些不顯示的內容
像是 `<span style="display:none">.....</span>` 這種使用者實際上是看不到的
另外,有些把「字體大小設為 0 」的部分也是一樣要過濾掉
濾掉這些之後,剩下的文字就是要抓的了
s4028600 iT邦新手 5 級 ‧ 2020-05-29 01:04:27 檢舉
我現在是強行將亂碼刪除
有什麼好的過濾法嗎?
soup.select好像無法...
listennn08 iT邦研究生 3 級 ‧ 2020-05-29 08:37:29 檢舉
不要用 bs4 啊
s4028600 iT邦新手 5 級 ‧ 2020-05-29 12:13:21 檢舉
@listennn08 因為處理內容我只會BS4
而且看樣子還是皮毛而已...

2 個回答

0
淺水員
iT邦新手 1 級 ‧ 2020-05-29 11:14:49
最佳解答

其實要過濾掉不要的內容
就真的去歷遍所有節點
判斷節點屬性後再決定是否輸出就好
要學爬蟲,最好先學 DOM 相關的內容,理解整份文件是一種樹狀結構
遇到比較複雜的狀況才知道怎麼處理

import requests
from bs4 import BeautifulSoup
from bs4.element import Tag,NavigableString

#這個函式會歷遍 node 節點的子元素
#過濾後輸出內容
def getArticleContent(node):
	outputHtml='';
	for child in node.children:
		#如果是 elementNode
		if(isinstance(child, Tag)):
			#判斷 style 屬性是否有 display:none 或 font-size:0px
			#有的話跳過這個 node
			st=child.attrs.get('style', '')
			if('display:none' in st or 'font-size:0px' in st):
				continue
			#通過檢查的 node 則用遞迴呼叫繼續往下
			outputHtml=outputHtml+getArticleContent(child)
		#如果是 textNode 就直接輸出文字內容
		elif(isinstance(child, NavigableString)):
			outputHtml=outputHtml+child
	return outputHtml

#測試的 html
testHtml='''<div id='test'><span style="display:none">不要的</span><font
style="font-size:0px;color:#FAFFEF">這也不要</font><br />
【標題】<font
style="font-size:0px;color:#FAFFEF">我不要看到這個</font><br />
內文內文內文內文 <font
style="font-size:0px;color:#FAFFEF">你看不到我</font><br /></div>'''

soup = BeautifulSoup(testHtml, 'html.parser');
div=soup.select('#test')[0];
print(getArticleContent(div))
看更多先前的回應...收起先前的回應...
s4028600 iT邦新手 5 級 ‧ 2020-05-29 12:10:24 檢舉


要理解一下
有沒看過的函數

我之前則是想出取代的方法
發問是想說有沒有直接爬取要的部分就好
看您的方式還是得要用過濾的方法
理解了
感謝

i=soup.select('.t_msgfont')[0]
a=i.text
for j in i.select('span'):
    a=a.replace(j.text,'',1)
    for f in i.select('font'):
        a=a.replace(f.text,'',1)

這是我的取代代碼
還蠻難看的...

淺水員 iT邦新手 1 級 ‧ 2020-05-29 12:15:00 檢舉

用任何一個 Library,看一下他們原始的文件是個好習慣,一般網路上教學只是入門教材。
參考: 官方的文件

s4028600 iT邦新手 5 級 ‧ 2020-05-29 12:39:44 檢舉

child.get('style', '')也和child.attrs.get('style', '')同樣結果
不懂attrs是什麼意思

淺水員 iT邦新手 1 級 ‧ 2020-05-29 12:58:27 檢舉

都可以,參考:Attributes

s4028600 iT邦新手 5 級 ‧ 2020-05-29 14:02:41 檢舉


以字典模式來看,然後用get取出
了解

1
Billour
iT邦新手 5 級 ‧ 2020-05-29 10:56:57

HI~!
關於你的問題,我覺得那是 網頁作者自已加上去的特殊符號。
圖片
https://ithelp.ithome.com.tw/upload/images/20200529/20126723G9zTXlSb9a.jpg
我把程式改成這樣就可以抓(grab )到網頁內容
https://ithelp.ithome.com.tw/upload/images/20200529/20126723JdhlkJrats.jpg
(一)以下是我的程式碼

import requests
from bs4 import BeautifulSoup
def ourl(url):
    res = requests.get(url)
    res.encoding = 'big5'
    soup1 = BeautifulSoup(res.text, 'html.parser')
    return soup1

url = 'http://ds-hk.net/thread-93278-1-49.html'
soup = ourl(url)
print(soup.select('.t_msgfont')[0])

(二)我在試成功上面的程式碼前,有先寫一個範例。
因為我之前沒有用過BeautifulSoup

from bs4 import BeautifulSoup

def ourl(url):
    res = requests.get(url)
    res.encoding = 'utf-8'
    soup = BeautifulSoup(res.text, 'html.parser')
    return soup

url = 'http://34.94.68.139/'
soup2 = ourl(url)
a_tags = soup2.select('html body h1')
for t in a_tags:
    print(t.text)

https://ithelp.ithome.com.tw/upload/images/20200529/201267235v5Ap17WRw.jpg


(三)出現大量錯誤。
我在試寫這個問題時,python3 的環境,有很多問題,
花了不少心力處理這一塊。

我應該寫一個「python3 常見錯誤」
或是 「python 環境設定」

之前,我是寫.net C# 安裝都是「下一步」「下一步」超級簡單,
但是,換到Linux python 後,最困難的是環境設定,
有時,要搞到一個星期,如果順利設定的話也要半個小時。

自已寫的詳細安裝錯誤狀況
http://www.okna.tw/zh-hant-tw/zp0001/

關於我

www.okna.tw


我要發表回答

立即登入回答