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

优采云 发布时间: 2020-08-17 20:22

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

  注意:

  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("")是从互联网采集,从一个外链跳转到另一个外链。

  仅运行getAllExternalLinks("")可以获取网站所有外链。

  说一下运行getAllExternalLinks("")遇到的问题,发生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=pile("^(/|.*" +includeurl+")")):的部份。为何要匹配以/开头的URL?

  不懂,留待之后解决吧。。。希望我别忘了。。。

   

  备注:

  BeautifulSoup的find()和find_all()

  BeautifulSoup里的find()和find_all()可能是你最常用的两个函数。借助它们,你可以通过标签的不同属性轻松地过滤HTML页面,查找须要的标签组或单个标签。

  BeautifulSoup文档地址:

  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文档的注释标签。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线