Python网络数据采集2-wikipedia

Python网络数据采集2-wikipedia

随机链接跳转

获取维基百科的词条超链接,并随机跳转。可能侧边栏和低栏会有其他链接。这不是我们想要的,所以定位到正文。正文在idbodyContentdiv标签里。

import random
import re
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
                  ' Chrome/52.0.2743.116 Safari/537.36 Edge/15.16193'}

start_url = '/wiki/Wiki'


def get_links(url):
    r = requests.get('https://en.wikipedia.org' + url, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    # /wiki/some_words
    link_list = soup.find('div', id='bodyContent').find_all('a', href=re.compile(r'^/wiki/[^/]*$'))
    return link_list


links = get_links(start_url)
while len(links) > 0:
    # 随机选择一个链接
    link = random.choice(links).get('href')
    print(link)
    # 新的词条覆盖了原来的超链接,一直搜寻
    links = get_links(link)
/wiki/Personal_wiki
/wiki/Database_management_system
/wiki/Netezza
/wiki/C%2B%2B
/wiki/C%2B%2B#Standardization
/wiki/ISO_9984
/wiki/Georgian_script
...

从首页开始,将首页的所有词条放入集合中(去重),再遍历集合,从集合中的链接递归搜索。

import re
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
                  ' Chrome/52.0.2743.116 Safari/537.36 Edge/15.16193'}

pages = set()


def get_links(url):
    global pages
    r = requests.get('https://en.wikipedia.org' + url, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    # /wiki/some_words
    link_list = soup.find('div', id='bodyContent').find_all('a', href=re.compile(r'^/wiki/[^:/]*$'))
    for link in link_list:
        if link['href'] not in pages:
            new_page = link['href']
            pages.add(new_page)
            print(new_page)
            get_links(new_page)


if __name__ == '__main__':
    # 空字符串表示,url为wiki主页https://en.wikipedia.org
    get_links('')

获取词条的标题、正文

标题在h1标签中,正文在id为mw-content-text的div标签中。

import re
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
                  ' Chrome/52.0.2743.116 Safari/537.36 Edge/15.16193'}

pages = set()


def get_links(url):
    global pages
    r = requests.get('https://en.wikipedia.org' + url, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    # /wiki/some_words
    try:
        print(soup.h1.string)
        # 只打印第一段
        print(soup.find(id='mw-content-text').find('p').text)
    except AttributeError:
        print('页面缺少一些属性。')

    link_list = soup.find('div', id='bodyContent').find_all('a', href=re.compile(r'^/wiki/[^:/]*$'))
    for link in link_list:
        if link['href'] not in pages:
            new_page = link['href']
            pages.add(new_page)
            print('----------\n' + new_page)
            get_links(new_page)


if __name__ == '__main__':
    # 空字符串表示,url为wiki主页https://en.wikipedia.org
    get_links('')
Main Page
Noye's Fludde is a one-act opera written largely for young amateur performers, created by the British composer Benjamin Britten. First performed in 1958 at the annual Aldeburgh Festival, it is based on the 15th-century Chester "mystery" play which recounts the biblical story of Noah, the flood and the ark. Britten had written numerous works for mixed 
...
--------
/wiki/Wikipedia
Wikipedia
Wikipedia (/ˌwɪkᵻˈpiːdiə/ ( listen) or /ˌwɪkiˈpiːdiə/ ( listen) WIK-i-PEE-dee-ə) is a free online encyclopedia with the aim to allow anyone to edit articles.[3] Wikipedia is the largest and most popular general reference work on the Internet[4][5][6] and is ranked among the ten most popular websites.[7] Wikipedia is owned by the nonprofit Wikimedia Foundation.[8][9][10]
--------
/wiki/Main_Page
...

寻找外链

https://www.oreilly.com开始不断寻找外链,如果某个页面没有外链,则进入该页面的某个内链,再重新找外链。感觉这个例子不是很好,因为从其他外链又可能回到初始页面。

import re
import random
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
                  ' Chrome/52.0.2743.116 Safari/537.36 Edge/15.16193'}


def get_random_external_link(start_page):
    r = requests.get(start_page, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    # 返回分割地址的第一个元素,一般是主页的地址
    ex_links = get_external_links(soup, split_address(start_page)[0])
    # 如果该页面没有外链,则获取内链,再从内链里随机选取一个,递归,直到获取到外链为止。
    if len(ex_links) == 0:
        internal_links = get_internal_links(soup, split_address(start_page)[0])
        return get_random_external_link(random.choice(internal_links))
    else:
        return random.choice(ex_links)


def get_internal_links(bs, include_url):
    internal_links = []
    # 找出所有以为'/'开头的链接,此为内链
    in_links = bs.find_all('a', href=re.compile(r'^/|' + include_url))
    for link in in_links:
        if link['href'] not in internal_links:
            internal_links.append(link['href'])

    return internal_links


def get_external_links(bs, exclude_url):
    external_links = []
    # 找出所有以http、https开头的链接,且不含内链字符的,此为外链,(?!...)表示不包含
    ex_links = bs.find_all('a', href=re.compile(r'^(https|http)((?!' + exclude_url + ').)*$'))
    for link in ex_links:
        if link['href'] not in external_links:
            external_links.append(link['href'])

    return external_links

 
def split_address(address):
    address_parts = []

    if address.split(':')[0] == 'http':
        address_parts = address.replace('http://', '').split('/')
    elif address.split(':')[0] == 'https':
        address_parts = address.replace('https://', '').split('/')

    return address_parts


# 只搜索外链
def follow_external_only(url):
    external_link = get_random_external_link(url)
    print(external_link)
    follow_external_only(external_link)


all_ex_links = set()
all_in_links = set()

# 获得所有外链和内链,并打印了外链
def get_all_external_links(url):
    r = requests.get(url, headers=headers)
    soup = BeautifulSoup(r.text, 'lxml')
    internal_links = get_internal_links(soup, split_address(url)[0])
    external_links = get_external_links(soup, split_address(url)[0])
    for link in external_links:
        if link not in all_ex_links:
            all_ex_links.add(link)
            print(link)

    for link in internal_links:
        if link not in all_in_links:
            all_in_links.add(link)
            get_all_external_links(link)


if __name__ == '__main__':
    # follow_external_only('https://www.oreilly.com')
    get_all_external_links('https://www.oreilly.com')
https://www.safaribooksonline.com/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170601+nav
http://shop.oreilly.com/
http://members.oreilly.com
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/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170710+homepage+get+started+now
https://www.safaribooksonline.com/public/free-trial/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170710+homepage+start+free+trial
https://www.safaribooksonline.com/accounts/login/?utm_medium=content&utm_source=oreilly.com&utm_campaign=lgen&utm_content=20170710+homepage+sign+in
...

上面的代码经常会出错,可能是正则表达式匹配的原因,也有可能是网络原因。


by @sunhaiyu

2017.7.14

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,380评论 25 707
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,722评论 1 92
  • 声明:本文讲解的实战内容,均仅用于学习交流,请勿用于任何商业用途! 一、前言 强烈建议:请在电脑的陪同下,阅读本文...
    Bruce_Szh阅读 12,672评论 6 28
  • 终 于,在来到深圳的第四个月里,迎来了你即将离开的消息。知道你要离开了,心里很怅然,不是为了我们毕业之后没有真正在...
    洛洛莉ya阅读 16,697评论 3 17
  • 领导人应该去学习唐僧,用人用长处,管人管到位
    逐味迹的伙伴们阅读 228评论 0 1