python 網(wǎng)絡(luò)爬蟲(chóng)-爬取網(wǎng)頁(yè)外部網(wǎng)站

前言

上一篇中我們?cè)诰S基百科的內(nèi)部網(wǎng)站上隨機(jī)跳轉(zhuǎn)進(jìn)入文章類(lèi)網(wǎng)頁(yè),而忽視外部網(wǎng)站鏈接贱鼻。本篇文章將處理網(wǎng)站的外部鏈接并試圖收集一些網(wǎng)站數(shù)據(jù)喻奥。和單個(gè)域名網(wǎng)站爬取不同,不同域名的網(wǎng)站結(jié)構(gòu)千差萬(wàn)別赖欣,這就意味我們的代碼需要更加的靈活以適應(yīng)不同的網(wǎng)站結(jié)構(gòu)屑彻。
因此,我們將代碼寫(xiě)成一組函數(shù)顶吮,這些函數(shù)組合起來(lái)就可以應(yīng)用在不同類(lèi)型的網(wǎng)絡(luò)爬蟲(chóng)需求社牲。

隨機(jī)跳轉(zhuǎn)外部鏈接

利用函數(shù)組,我們可以在50行左右滿足爬取外部網(wǎng)站的需求悴了。
示例代碼:

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
import datetime
import random
from urllib.parse import quote

pages = set()
random.seed(datetime.datetime.now())


''' 獲取一個(gè)網(wǎng)頁(yè)的所有互聯(lián)網(wǎng)鏈接'''

# 獲取網(wǎng)頁(yè)所有內(nèi)部鏈接
def get_internal_links(soup, include_url):
    internal_links = []
    # find all links that befin with a '/'
    print(include_url)
    for link in soup.find_all('a',
                              href=re.compile(r'^((/|.)*' + include_url + ')')):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in internal_links:
                internal_links.append(link.attrs['href'])
    return internal_links


# retrieves a list of all external links found on a page
#獲取網(wǎng)頁(yè)上所有外部鏈接
def get_external_links(soup, exclude_url):
    external_links = []
    # Finds all links that starts with 'http' or 'www' that do not contain the
    # current URL
    for link in soup.find_all('a',
                              href=re.compile(r'^(http|www)((?!' + exclude_url + ').)*$')):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in external_links:
                external_links.append(link.attrs['href'])
    return external_links


#拆分網(wǎng)址獲取主域名
def split_address(address):
    address_parts = address.replace('http://', '').split('/')
    return address_parts


#隨機(jī)外部鏈接跳轉(zhuǎn)
def get_random_external_link(starting_page):
    html = urlopen(starting_page)

    soup = BeautifulSoup(html, 'lxml')
    external_links = get_external_links(
        soup, split_address(starting_page)[0])  # find the domain URL
    if len(external_links) == 0:
        internal_links = get_internal_links(soup, starting_page)
        print(len(internal_links))
        return get_external_links(soup,
                                  internal_links[random.randint(0, len(internal_links) - 1)])
    else:
        return external_links[random.randint(0, len(external_links) - 1)]



hop_count = set()

#只跳轉(zhuǎn)外部鏈接搏恤,設(shè)置跳轉(zhuǎn)次數(shù)loop, 默認(rèn)跳轉(zhuǎn)5次
def follow_external_only(starting_site, loop=5):
    global hop_count
    external_link = get_random_external_link(
        quote(starting_site, safe='/:?='))
    print('Random external link is: ' + external_link)
    while len(hop_count) < loop:
        hop_count.add(external_link)
        print(len(hop_count))
        follow_external_only(external_link)



follow_external_only("http://www.baidu.com")

由于代碼沒(méi)有異常處理和反反爬蟲(chóng)處理,因此一定會(huì)報(bào)錯(cuò)湃交。由于跳轉(zhuǎn)是隨機(jī)的熟空,可以多運(yùn)行幾次,有興趣的可以根據(jù)每次的報(bào)錯(cuò)原因完善代碼搞莺。
輸出結(jié)果:

Random external link is: http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&ie=utf-8&word=
1
Random external link is: http://baishi.baidu.com/watch/6388818335201070269.html
2
Random external link is: http://v.baidu.com/tv/
3
Random external link is: http://player.baidu.com/yingyin.html
4
Random external link is: http://help.baidu.com/question?prod_en=player
5
Random external link is: http://home.baidu.com
[Finished in 6.3s]

抓取網(wǎng)頁(yè)上所有外部鏈接

把代碼寫(xiě)成函數(shù)的好處是可以簡(jiǎn)單地修改或者添加以滿足不同的需求而不會(huì)破壞代碼息罗。比如:
目的:爬取整個(gè)網(wǎng)頁(yè)所有外部鏈接并對(duì)每個(gè)鏈接標(biāo)記
我們可以添加如下函數(shù):

# Collects a list of all external URLs found on the site
all_ext_links = set()
all_int_links = set()


def get_all_external_links(site_url):
    html = urlopen(site_url)
    soup = BeautifulSoup(html, 'lxml')
    print(split_address(site_url)[0])
    int
    internal_links = get_internal_links(soup, split_address(site_url)[0])
    external_links = get_external_links(soup, split_address(site_url)[0])
    for link in external_links:
        if link not in all_ext_links:
            all_ext_links.add(link)
            print(link)
    for link in internal_links:
        if link not in all_int_links:
            print('About to get link: ' + link)
            all_int_links.add(link)
            get_all_external_links(link)

# follow_external_only("http://www.baidu.com")
get_all_external_links('http://oreilly.com')

輸出結(jié)果如下:

oreilly.com
oreilly.com
https://cdn.oreillystatic.com/pdf/oreilly_high_performance_organizations_whitepaper.pdf
http://twitter.com/oreillymedia
http://fb.co/OReilly
https://www.linkedin.com/company/oreilly-media
https://www.youtube.com/user/OreillyMedia
About to get link: https://www.oreilly.com
https:
https:
https://www.oreilly.com
http://www.oreilly.com/ideas
https://www.safaribooksonline.com/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170601+nav
http://www.oreilly.com/conferences/
http://shop.oreilly.com/
http://members.oreilly.com
https://www.oreilly.com/topics
https://www.safaribooksonline.com/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170505+homepage+get+started+now
https://www.safaribooksonline.com/accounts/login/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170203+homepage+sign+in
https://www.safaribooksonline.com/live-training/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170201+homepage+take+a+live+online+course
https://www.safaribooksonline.com/learning-paths/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170201+homepage+follow+a+path
https://www.safaribooksonline.com/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170505+homepage+unlimited+access
http://www.oreilly.com/live-training/?view=grid
https://www.safaribooksonline.com/your-experience/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170201+homepage+safari+platform
https://www.oreilly.com/ideas/8-data-trends-on-our-radar-for-2017?utm_medium=referral&utm_source=oreilly.com&utm_campaign=lgen&utm_content=link+2017+trends
https://www.oreilly.com/ideas?utm_medium=referral&utm_source=oreilly.com&utm_campaign=lgen&utm_content=link+read+latest+articles
http://www.oreilly.com/about/
http://www.oreilly.com/work-with-us.html
http://www.oreilly.com/careers/
http://shop.oreilly.com/category/customer-service.do
http://www.oreilly.com/about/contact.html
http://www.oreilly.com/emails/newsletters/
http://www.oreilly.com/terms/
http://www.oreilly.com/privacy.html
http://www.oreilly.com/about/editorial_independence.html
About to get link: https://www.safaribooksonline.com/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170601+nav
https:
https:
https://www.oreilly.com/
About to get link: https://www.oreilly.com/
https:
https:
About to get link: https://www.oreilly.com/topics
......

程序會(huì)一直循環(huán)下去直到達(dá)到python默認(rèn)的循環(huán)極限, 有興趣的朋友可以像上面的代碼一樣添加默認(rèn)循環(huán)限制loop=5才沧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迈喉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子温圆,更是在濱河造成了極大的恐慌挨摸,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岁歉,死亡現(xiàn)場(chǎng)離奇詭異得运,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)刨裆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)澈圈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人帆啃,你說(shuō)我怎么就攤上這事瞬女。” “怎么了努潘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵诽偷,是天一觀的道長(zhǎng)坤学。 經(jīng)常有香客問(wèn)我,道長(zhǎng)报慕,這世上最難降的妖魔是什么深浮? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮眠冈,結(jié)果婚禮上飞苇,老公的妹妹穿的比我還像新娘。我一直安慰自己蜗顽,他們只是感情好布卡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著雇盖,像睡著了一般忿等。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上崔挖,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天贸街,我揣著相機(jī)與錄音,去河邊找鬼狸相。 笑死薛匪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卷哩。 我是一名探鬼主播蛋辈,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼将谊!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起渐白,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤尊浓,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后纯衍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體栋齿,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年襟诸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓦堵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歌亲,死狀恐怖菇用,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陷揪,我是刑警寧澤惋鸥,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布杂穷,位于F島的核電站,受9級(jí)特大地震影響卦绣,放射性物質(zhì)發(fā)生泄漏耐量。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一滤港、第九天 我趴在偏房一處隱蔽的房頂上張望廊蜒。 院中可真熱鬧,春花似錦溅漾、人聲如沸山叮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)聘芜。三九已至,卻和暖如春缝龄,著一層夾襖步出監(jiān)牢的瞬間汰现,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工叔壤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞎饲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓炼绘,卻偏偏與公主長(zhǎng)得像嗅战,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俺亮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容