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

Python网络数据采集2-wikipedia的更多相关文章

  1. 笔记之Python网络数据采集

    笔记之Python网络数据采集 非原创即采集 一念清净, 烈焰成池, 一念觉醒, 方登彼岸 网络数据采集, 无非就是写一个自动化程序向网络服务器请求数据, 再对数据进行解析, 提取需要的信息 通常, ...

  2. Python网络数据采集7-单元测试与Selenium自动化测试

    Python网络数据采集7-单元测试与Selenium自动化测试 单元测试 Python中使用内置库unittest可完成单元测试.只要继承unittest.TestCase类,就可以实现下面的功能. ...

  3. Python网络数据采集3-数据存到CSV以及MySql

    Python网络数据采集3-数据存到CSV以及MySql 先热热身,下载某个页面的所有图片. import requests from bs4 import BeautifulSoup headers ...

  4. [python] 网络数据采集 操作清单 BeautifulSoup、Selenium、Tesseract、CSV等

    Python网络数据采集操作清单 BeautifulSoup.Selenium.Tesseract.CSV等 Python网络数据采集操作清单 BeautifulSoup.Selenium.Tesse ...

  5. Python网络数据采集6-隐含输入字段

    Python网络数据采集6-隐含输入字段 selenium的get_cookies可以轻松获取所有cookie. from pprint import pprint from selenium imp ...

  6. Python网络数据采集4-POST提交与Cookie的处理

    Python网络数据采集4-POST提交与Cookie的处理 POST提交 之前访问页面都是用的get提交方式,有些网页需要登录才能访问,此时需要提交参数.虽然在一些网页,get方式也能提交参.比如h ...

  7. Python网络数据采集1-Beautifulsoup的使用

    Python网络数据采集1-Beautifulsoup的使用 来自此书: [美]Ryan Mitchell <Python网络数据采集>,例子是照搬的,觉得跟着敲一遍还是有作用的,所以记录 ...

  8. Python网络数据采集PDF

    Python网络数据采集(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/16c4GjoAL_uKzdGPjG47S4Q 提取码:febb 复制这段内容后打开百度网盘手 ...

  9. python网络数据采集的代码

    python网络数据采集的代码 https://github.com/REMitchell/python-scraping

随机推荐

  1. 轻松Angularjs实现表格按指定列排序

    angular表格点击序号进行升序,再次点击进行降序排序,在输入框输入信息,出现相对应数据的那一行. html: <input type="text" ng-model=&q ...

  2. 20170422早会训话,ps:程序出现两次BUG,领导很生气

    针对这种问题: 要讲3点 1.有没有拖团队后腿: 作为一名前端开发人员,对于前端开发的任务,我能够在第一时间完成,保证时间进度,但光做到这一点是不够的,不能只讲究任务,不考虑结果,会不会出现问题造成其 ...

  3. 【RAC】RAC相关基础知识

    [RAC]RAC相关基础知识 1.CRS简介    从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁. ...

  4. eclipse在多modules项目结构下避免模块间依赖引用的场景

    这个在单一classLoader时,不会有问题.如果多classloader下会有问题. 假设工程有两个模块,module2 依赖module1 当我们执行mvc eclipse:eclipse后,然 ...

  5. 并发编程(三):从AQS到CountDownLatch与ReentrantLock

    一.目录      1.AQS简要分析      2.谈CountDownLatch      3.谈ReentrantLock      4.谈消费者与生产者模式(notfiyAll/wait.si ...

  6. Java添加JDBC

    添加JDBC 1.SQL Server SQL Server2005 下载 sqljdbc_4.0 https://www.microsoft.com/en-us/download/details.a ...

  7. mongodb远程连接配置

    mongodb远程连接配置如下: 1.修改配置文件mongodb.conf 命令:vim /etc/mongodb.conf 把 bind_ip=127.0.0.1 这一行注释掉或者是修改成 bind ...

  8. 安卓巴士android源码、博文精选1

      每周精选 第 53 期   精品源码 Android开源项目--CookMan 厨客APP     简介CookMan,厨客,是一款查询.搜索.分类.收藏菜谱功能的APP.|52数据来源Mob A ...

  9. JanaScript数据类型

    数据类型 一.基础类型值包括:undefined.null.boolean.string.number 基础类型分别在内存中占有大小空间,它们的值保存在栈空间,我们通过按值来访问. undefined ...

  10. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...