python网络数据采集笔记(一)

注意:html

1.为了不一个页面被采集两次, 连接去重是很是重要的。
2.写代码以前拟个大纲或画个流程图是很好的编程习惯,这么作不只能够为你后期处理节省
不少时间,更重要的是能够防止本身在爬虫变得愈来愈复杂时乱了分寸。
3.处理网页重定向
正则表达式

  •服务器端重定向,网页在加载以前先改变了 URL
  • 客户端重定向,有时你会在网页上看到“10 秒钟后页面自动跳转到……”之类的消息,
  表示在跳转到新 URL 以前网页须要加载内容。
编程

  服务器端重定向,你一般不用担忧。若是你在用 Python 3.x 版本的 urllib 库,它会自
  动处理重定向。不过要注意,有时候你要采集的页面的 URL 可能并非你当前所在页
  面的 URL
服务器

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


pages = set()
#随机数种子
random.seed(datetime.datetime.now())

#获取页面全部内链的列表
def getInternalLinks(bsObj, includeurl):
    internalLinks = []
    #匹配以/开头的字符串,或匹配包括includeurl的字符串,+表示字符串拼接。
    for link in bsObj.find_all("a", href=re.compile("^(/|.*" +includeurl+")")):
    #for link in bsObj.find_all("a", href=re.compile("^(.*" + includeurl + ")")):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in internalLinks:
                internalLinks.append(link.attrs['href'])
    return internalLinks

#获取页面内全部外链的列表
def getExternalLinks(bsObj, excludeurl):
    externalLinks = []
    # 找出全部以"http""www"开头且不包含当前URL的连接
    for link in bsObj.find_all("a", href=re.compile("^(http|www)((?!" +excludeurl+").)*$")):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in externalLinks:
                externalLinks.append(link.attrs['href'])
    return externalLinks

#URL连接切片,为了得到域名
def splitAddress(adress):
    adressParts = adress.replace("http://", "").split("/")
    return adressParts

#于外链列表中随机选取一条外链
def getRandomExternalLink(startingpage):
    html = urlopen(startingpage)
    bsObj = BeautifulSoup(html, "lxml")
    externalLinks = getExternalLinks(bsObj, startingpage)
    if len(externalLinks) == 0:
        internalLinks = getInternalLinks(startingpage)
        return getExternalLinks(internalLinks[random.randint(0, len(internalLinks)-1)])
    else:
        return externalLinks[random.randint(0, len(externalLinks)-1)]

#外链跳转,从一条外链跳转到另外一条
def followExternalOnly(siteurl):
    externalLink = getRandomExternalLink(siteurl)
    print("随机外链:", externalLink)
    followExternalOnly(externalLink)

#收集网站内全部外链列表
allExtLinks = set()
allIntLinks = set()

def getAllExternalLinks(siteurl):
    html = urlopen(siteurl)
    bsObj = BeautifulSoup(html, "lxml")
    internalLinks = getInternalLinks(bsObj, splitAddress(siteurl)[0])
    externalLinks = getExternalLinks(bsObj, splitAddress(siteurl)[0])
    for link in externalLinks:
        if link not in allExtLinks:
            allExtLinks.add(link)
            print(link)
    for link in internalLinks:
        if link not in allIntLinks:
            allIntLinks.add(link)
            print("即将获取连接的URL是:"+link)
            getAllExternalLinks(link)

#从互联网采集,从一个外链跳转到另外一个外链
#followExternalOnly("http://oreilly.com")
#获取网站全部外链
getAllExternalLinks("http://oreilly.com")

说明:以上代码能够执行两个功能。仅运行followExternalOnly("http://oreilly.com")是从互联网采集,从一个外链跳转到另外一个外链。app

  仅运行getAllExternalLinks("http://oreilly.com")能够获取网站全部外链。dom

说一下运行getAllExternalLinks("http://oreilly.com")遇到的问题,发生raise ValueError("unknown url type: %r" % self.full_url),ValueError: unknown url type: '/oscon/oscon-or/schedule'函数

是否是问题出如今获取页面全部内链函数getInternalLinks()的for link in bsObj.find_all("a", href=re.compile("^(/|.*" +includeurl+")")):的部分。为什么要匹配以/开头的URL?网站

不懂,留待之后解决吧。。。但愿我别忘了。。。ui

 

备注:
url

BeautifulSoup的find()find_all()

BeautifulSoup里的find()find_all()多是你最经常使用的两个函数。借助它们,你能够经过标签的不一样属性轻松地过滤HTML页面,查找须要的标签组或单个标签。

BeautifulSoup文档地址:http://beautifulsoup.readthedocs.io

find()函数语法:

find( name , attrs , recursive , string , **kwargs ) 

find_all()函数语法:

find_all( name , attrs , recursive , string , **kwargs ) 

搜索当前tag的全部tag子节点,并判断是否符合过滤器的条件。

name参数能够查找全部名字为name的tag,字符串对象会被自动忽略掉。搜索 name参数的值可使任一类型的过滤器,字符串,正则表达式,列表,方法等。

attrs参数定义一个字典参数来搜索包含特殊属性的tag

经过string参数能够搜搜文档中的字符串内容,与name参数的可选值同样。

keyword参数:若是一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数看成指定名字tag的属性来搜索。

find_all()方法返回所有的搜索结构,若是文档树很大那么搜索会很慢。若是咱们不须要所有结果,可使用 limit参数限制返回结果的数量.效果与SQL中的limit关键字相似,当搜索到的结果数量达到limit的限制时,就中止搜索返回结果。

find 等价于 find_all 的 limit 等于 1 ;

调用tag的 find_all()方法时,Beautiful Soup会检索当前tag的全部子孙节点,若是只想搜索tag的直接子节点,可使用参数 recursive=False

其余BeautifulSoup对象

NavigableString对象:表示标签里面的文字;
Comment对象:用来查找HTML文档的注释标签。

相关文章
相关标签/搜索