日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python实现新闻网站_如何用 100 行 Python 代码实现新闻爬虫?这样可算成功?

發布時間:2025/3/19 python 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现新闻网站_如何用 100 行 Python 代码实现新闻爬虫?这样可算成功? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

每天我都要坐地鐵上班,而地鐵里信號差。但我希望在坐地鐵的時候讀些新聞,于是就寫了下面這個新聞爬蟲。我并沒有打算做很漂亮的應用,所以只完成了原型,它可以滿足我最基本的需求。其思路很簡單:

找到新聞源;用Python抓取新聞;利用BeautifulSoup分析HTML并提取出內容;轉換成容易閱讀的格式并通過郵件發送。

下面詳細介紹每個部分的實現。

新聞源:Reddit

我們可以通過Reddit提交新聞鏈接并為之投票,因此Reddit是個很好的新聞來源。但接下來的問題是:怎樣才能獲取每天最流行的新聞?在考慮抓取之前,我們應該先考慮目標網站有沒有提供API。因為使用API完全合法,更重要的是它能提供機器可讀的數據,這樣就無需再分析HTML了。幸運的是Reddit提供了API。我們可以從API列表中找到所需的功能:/top。該功能可以返回Reddit或指定subreddit上最流行的新聞。接下來的問題是:這個API怎么用?仔細閱讀了Reddit的文檔之后,我找到了最有效的用法。第一步:在Reddit上創建一個應用。登錄之后前往“preferences → apps”頁面,底部有個名為“create another app...”的按鈕。點擊后創建一個“script”類型的應用。我們不需要提供“about url”或“redirect url”,因為這個應用不對公眾開放,也不會被別人使用。

應用創建之后,可以在應用信息里找到App ID和Secret。

下個問題是如何使用App ID和Secret。由于我們只需獲取指定SubReddit上最流行的新聞,而無需訪問任何與用戶相關的信息,所以理論上來說我們無需提供用戶名或密碼之類的個人信息。Reddit提供了“Application Only OAuth”(https://github.com/reddit-archive/reddit/wiki/OAuth2#application-only-oauth)的形式,通過這種方式,應用可以匿名訪問公開的信息。運行下面這條命令:

$ curl -X POST -H'User-Agent: myawesomeapp/1.0'-d grant_type=client_credentials--user 'OUR_CLIENT_ID:OUR_CLIENT_SECRET' https://www.reddit.com/api/v1/access_token

該命令會返回access token:

{"access_token":"ABCDEFabcdef0123456789","token_type":"bearer","expires_in": 3600,"scope":"*"}

太好了!有了access token之后就可以大展拳腳了。最后,如果不想自己寫API的訪問代碼的話,可以使用Python客戶端:https://github.com/praw-dev/praw先做一下測試,從/r/Python獲取最流行的5條新聞:

>>> import praw

>>> import pprint

>>> reddit = praw.Reddit(client_id='OUR_CLIENT_ID',

... client_secret='OUR_SECRET',

... grant_type='client_credentials',

... user_agent='mytestscript/1.0')

>>> subs = reddit.subreddit('Python').top(limit=5)

>>> pprint.pprint([(s.score, s.title) forsinsubs])

[(6555, 'Automate the boring stuff with python - tinder'),

(4548,

'MS is considering official Python integration with Excel, and is asking for '

'input'),

(4102, 'Python Cheet Sheet for begineers'),

(3285,

'We started late, but we managed to leave Python footprint on r/place!'),

(2899, "Python Section at Foyle's, London")]

成功了!

抓取新聞頁面

下一步的任務是抓取新聞頁面,這其實很簡單。通過上一步我們可以得到Submission對象,其URL屬性就是新聞的地址。我們還可以通過domain屬性過濾掉那些屬于Reddit自己的URL:

subs = [subforsubinsubs ifnotsub.domain.startswith('self.')]

我們只需要抓取該URL即可,用Requests很容易就可以做到:

forsubinsubs:

res = requests.get(sub.url)

if (res.status_code == 200 and'content-type'inres.headersand

res.headers.get('content-type').startswith('text/html')):

html = res.text

這里我們略過了content type不是text/html的新聞地址,因為Reddit的用戶有可能會提交直接指向圖片的鏈接,我們不需要這種。

提取新聞內容

下一步是從HTML中提取內容。我們的目標是提取新聞的標題和正文,而且可以忽略其他不需要閱讀的內容,如頁首、頁腳、側邊欄等。這項工作很難,其實并沒有通用的完美解決辦法。雖然BeautifulSoup可以幫我們提取文本內容,但它會連頁首頁腳一起提取出來。不過幸運的是,我發現目前網站的結構比以前好很多。沒有表格布局,也沒有和和
,整個文章頁面清晰地用

標出了標題和每個段落。而且絕大部分網站會把標題和正文放在同一個容器元素中,比如像這樣:

Site Navigation

Page Title

Paragraph 1

Paragraph 2

Sidebar

Copyright...

這個例子中頂層的

就是用于標題和正文的容器。所以可以利用如下算法找到正文:

找到

作為標題。出于SEO的目的,通常頁面上只會有一個

;

找到

的父元素,檢查該父元素是否包含足夠多的

;

重復第2步,直到找到一個包含足夠多

的父元素,或到達

元素。如果找到了包含足夠

的父元素,則該父元素就是正文的容器。如果在找到足夠的

之前遇到了

,說明頁面不包含任何可供閱讀的內容。

這個算法雖然非常簡陋,并沒有考慮任何語義信息,但完全行得通。畢竟,算法運行失敗時只需要忽略掉那篇文章就行了,少讀一篇文章沒什么大不了的……當然你可以通過解析、或#main、.sidebar等語義元素來實現更準確的算法。用這個算法可以很容易地寫出解析代碼:

soup = BeautifulSoup(text,'html.parser')

# find the article title

h1 = soup.body.find('h1')

# find the common parent for

andall

s.

root = h1

while root.name!='body'andlen(root.find_all('p')) < 5:

root = root.parent

if len(root.find_all('p')) < 5:

returnNone

# find allthe content elements.

ps = root.find_all(['h2','h3','h4','h5','h6','p','pre'])

這里我利用len(root.find_all('p')) < 5作為正文過濾的條件,因為真正的新聞不太可能少于5個段落。大家可以根據需要調整這個值。

轉換成易于閱讀的格式

最后一步是將提取出的內容轉換為易于閱讀的格式。我選擇了Markdown,不過你可以寫出更好的轉換器。本例中我只提取了和和

,所以簡單的函數就能滿足要求:

ps = root.find_all(['h2','h3','h4','h5','h6','p','pre'])

ps.insert(0, h1) #addthe title

content = [tag2md(p) forpinps]

def tag2md(tag):

if tag.name=='p':

returntag.text

elif tag.name=='h1':

returnf'{tag.text}\n{"=" * len(tag.text)}'

elif tag.name=='h2':

returnf'{tag.text}\n{"-" * len(tag.text)}'

elif tag.namein['h3','h4','h5','h6']:

returnf'{"#" * int(tag.name[1:])} {tag.text}'

elif tag.name=='pre':

returnf'```\n{tag.text}\n```'

完整的代碼

我在Github上分享了完整的代碼,鏈接如下:https://gist.github.com/charlee/bc865ba8aac295dd997691310514e515正好100行 ,跑一下試試:

Scraping /r/Python...

- Retrieving https://imgs.xkcd.com/comics/python_environment.png

x fail ornothtml

- Retrieving https://thenextweb.com/dd/2017/04/24/universities-finally-realize-java-bad-introductory-programming-language/#.tnw_PLAz3rbJ

=> done, title = "Universities finally realize that Java is a bad introductory programming language"

- Retrieving https://github.com/numpy/numpy/blob/master/doc/neps/dropping-python2.7-proposal.rst

x fail ornothtml

- Retrieving http://www.thedurkweb.com/sms-spoofing-with-python-for-good-and-evil/

=> done, title = "SMS Spoofing with Python for Good and Evil"

...

抓取的新聞文件:

最后需要做的是將這個腳本放在服務器上,設置好cronjob每天跑一次,然后將生成的文件發到我的信箱。我沒有花太多時間關注細節,所以其實這個腳本還有很多值得改進的地方。有興趣的話你可以繼續添加更多的功能,如提取圖像等。

【編輯推薦】

【責任編輯:未麗燕 TEL:(010)68476606】

點贊 0

總結

以上是生活随笔為你收集整理的python实现新闻网站_如何用 100 行 Python 代码实现新闻爬虫?这样可算成功?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。