爬虫入门(三)进阶技巧之ID遍历、追踪链接
1.使用id遍历
(1)原理
使用id遍历网页是常见的做法,由于大多数网站存储的数据太多,不可能为每一个网页都起名字,便用id做标记使得数据库方便识别,这也使得按id遍历网页成为可能。
在示例网站:http://example.python-scraping.com
我们可以用两种方式访问同一网页:http://example.python-scraping.com/view/Afghanistan-1
http://example.python-scraping.com/view/1
所以我们只要每次改变一下尾部的id就可以方便的遍历该网站的所有国家页面
(2)问题
避免因为某个页面被删除、隐藏或者id的缺号而意外终止,设置最大出错数,不至于一遇到id缺号就停止,如此一来只有连续出错多次程序才会结束
由于不知道id到哪里结束,我们还需要一个无线迭代器,产生从1开始的整数逐步增大直到程序停止。使用itertools模块。该模块是一个无穷迭代器,其中itertools.count(start [,step])函数创建一个从start开始,步长为step的迭代器,默认为1
(3)实现
import itertools
import urllib.request
from urllib.error import URLError, HTTPError, ContentTooShortError
import re#以Chrom为默认代理,默认重试两次的爬取网页封装函数;获取网页指定的解码格式,否则使用默认的'utf-8'格式
def GetData(url, proxy='', retry=2, charset = 'utf-8'):print('download : ' + url)if proxy == '':proxy = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11'request = urllib.request.Request(url)request.add_header('User-Agent', proxy)try:response = urllib.request.urlopen(request)cs = response.headers.get_content_charset()if not cs:cs = charsethtml = response.read().decode(cs)# print(html) 当前只是打印页面,之后可以修改为保存爬取的页面except (URLError, HTTPError, ContentTooShortError) as e:print('download error :', e.reason)if retry > 0: # 递归重试下载if hasattr(e, 'code') and 500 < e.code < 600:GetData(url, proxy, retry - 1)return html#利用字符串的format函数拼接url和id,避免因为某个页面被删除、隐藏或者id的缺号而意外终止
# 设置最大出错数,即max_error默认为5,不至于一遇到id缺号就停止
def scrap_byID(url, max_error=5):for page in itertools.count(1):pg_url = '{}{}'.format(url,page)html = GetData(pg_url)if html is None:max_error -= 1if max_error == 0:break
url = 'http://example.python-scraping.com/view/'
scrap_byID(url)
2.追踪链接
跟踪网页中的链接,利用正则表达式只访问感兴趣的内容。其实就是获取起始页面中的所有链接,通过正则表达式过滤出我们感兴趣的链接访问,再新打开的页面中再做同样的事情,从而追踪下去。
(1)用到的库及遇到的问题
一、正则表达式的设定和匹配
当我们在Python中使用正则表达式时,re模块内部会干两件事情:
编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
用编译后的正则表达式去匹配字符串。
那么如果一个正则表达式要重复使用几千次,出于效率的考虑,我们是不是应该先把这个正则先预编译好, 接下来重复使用时就不再需要编译这个步骤了,直接匹配,提高我们的效率。
1.compile(pattern, flags=0)函数,预编译十分的简单,re.compile()即可,编译后生成Regular Expression对象。 pattern 指定编译时的表达式字符串 flags 编译标志位,用来修改正则表达式的匹配方式。支持 re.L|re.M 同时匹配 :
- re.I(re.IGNORECASE) :使匹配对大小写不敏感
- re.L(re.LOCAL) :做本地化识别(locale-aware)匹配
- re.M(re.MULTILINE) :多行匹配,影响 ^ 和 $
- re.S(re.DOTALL) :使 . 匹配包括换行在内的所有字符
- re.U(re.UNICODE):根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
- re.X(re.VERBOSE):该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
2.re.match(正则表达式,要匹配的字符串)函数进行匹配
3.re库的findall(pattern, string, flags=0)函数,返回string中所有与pattern匹配的全部字符串,返回形式为列表。
二、正则匹配的链接标签
1.^在正则表达式中的应用
表示起始定界符
如:'abc'表示字符串中有'abc'就匹配成功
'[abc]'表示字符串中有'a'或'b'或'c'就匹配成功
'^abc'表示字符串由'abc'开头就匹配成功
'^[abc]'表示字符串由'a'或'b'或'c'开头的,
表示取反
当^表示取反的时候,只有一种情况,就是在中括号里面,而且是每一个字符之外的。 所以千万不要把'[^abc]'看成是对'abc'字符串的取反。如:
'[^abc]'表示匹配'a','b','c'之外的字符。如果一个字符串是由'a','b','c'组合起来的,那就是假。
2.a标签的格式
这是抓取的html页面中a标签的形式<a href="/places/default/view/Afghanistan-1">Afghanistan</a>
href指向的就是链接,可以很明显看到这里给出的是相对链接,即相对主页面的链接
所以我们要对链接做一些拼接操作,将诸如'http://www.xxx.com/'拼接在前面,
拼接用到的模块为urllib.parse的urljoin函数 #urljoin('index1', 'index2')连接两个参数的url, 将第二个参数中缺的部分用第一个参数的补齐,如果第二个有完整的路径,则以第二个为主。
三、定义多行字符串
使用三引号
如:str1 = """Le vent se lève, il faut tenter de vivre.
起风了,唯有努力生存。
(纵有疾风起,人生不言弃。)""" 三对 双引号单引号都可以
使用小括号
如: str3 = ('Le vent se lève, il faut tenter de vivre.'
'起风了,唯有努力生存。'
'(纵有疾风起,人生不言弃。)')
这样做的好处是避免了对特殊字符的转义
四、重复下载问题、
由于这些链接之间有可能重复,比如a页面有链接指向b页面,b页面也有链接指向a页面,有可能会重复下载甚至死循环,我们要避免这种情况 。设置一个seen队列储存已经存储过的页面,这样新链接到达时只要不在seen队列中,就意味着没有下载过。
(2)代码实现
import re
from urllib.parse import urljoin
import urllib.request
from urllib.error import URLError, HTTPError, ContentTooShortError#以Chrom为默认代理,默认重试两次的爬取网页封装函数;获取网页指定的解码格式,否则使用默认的'utf-8'格式
def GetData(url, proxy='', retry=2, charset = 'utf-8'):print('download : ' + url)if proxy == '':proxy = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11'request = urllib.request.Request(url)request.add_header('User-Agent', proxy)try:response = urllib.request.urlopen(request)cs = response.headers.get_content_charset()if not cs:cs = charsethtml = response.read().decode(cs)# print(html) 当前只是打印页面,之后可以修改为保存爬取的页面except (URLError, HTTPError, ContentTooShortError) as e:print('download error :', e.reason)if retry > 0: # 递归重试下载if hasattr(e, 'code') and 500 < e.code < 600:GetData(url, proxy, retry - 1)return html#获取一个页面跟踪到的符合正则表达式的链接,此正则式仅针对链接后的目录
def scrap_link(start_url, link_regex):crawl_queue = [start_url]seen = [start_url] # seen = set(crawl_queue) set函数返回‘set’对象,可以用seen.add()添加元素while crawl_queue :url = crawl_queue.pop()html = GetData(url)if html is None:continuefor link in getlinks(html):print(link)print(re.match(link_regex, link))if re.match(link_regex,link):abs_link = urljoin(start_url, link)if abs_link not in seen:crawl_queue.append(abs_link)seen.append(abs_link)
#返回一个页面的所有a标签的链接
def getlinks(html):url_regex = re.compile("""<a[^>]+href=["'](.*?)["']""", re.IGNORECASE)return url_regex.findall(html) #或者re.findall(url_regex, html, re.IGNORECASE)#调用函数
scrap_link('http://example.python-scraping.com', '/places/default/(index|view)/')
爬虫入门(三)进阶技巧之ID遍历、追踪链接相关推荐
- [转载]Python爬虫入门三之Urllib库的基本使用
python爬虫系列教程http://cuiqingcai.com/1052.html 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优 ...
- python爬虫 入门+进阶_python爬虫入门到进阶(三)
本节: 带Cookies的访问 设置headers访问绕过网站检测 设置Headers 有些网站会验证访问者是否合法,所以上一节的访问方式在一些网站就会失灵 ,网站对请求不予以响应,为了模拟浏览器工作 ...
- Python爬虫入门与进阶
目录 一.学习搭建网站 二.requests库入门 1.安装(在python中) 2.主要方法 3.对象的属性 4.requests库主要功能 三.requests库进阶 1.requests异常 2 ...
- 爬虫入门三(获取各国网址,三种网页抓取方法,下载缓存)
对<用Python写网络爬虫>进行了总结归纳. 1.爬相关地址 #coding=utf-8 import robotparser import urlparse import urllib ...
- Python爬虫入门三之Urllib库的基本使用
转自:http://cuiqingcai.com/947.html 那么接下来,小伙伴们就一起和我真正迈向我们的爬虫之路吧. 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信 ...
- java获取b站动态列表地址_爬虫入门(三)爬取b站搜索页视频分析(动态页面,DBUtils存储)...
这一次终于到了分析b站视频了.开始体会到写博客非常占用学技术的时间,但是还是希望能总结,沉淀下来. 工具:使用Webmaigc框架,DBUtils,C3P0连接池. 分析过程:b站的搜索页面是这样的. ...
- Python爬虫入门三urllib库基本使用
urllib是一个收集了多个涉及了URL的模块的包: URL获取网页 urllibtest.pyimport urllib2 response = urllib2.urlopen('http://ww ...
- python简单爬虫入门一_Python简单爬虫入门三
我们继续研究BeautifulSoup分类打印输出 前两部主要讲述我们如何用BeautifulSoup怎去抓取网页信息以及获取相应的图片标题等信息, 等于我们已经只知道如何用工具去浏览和检索内容,但是 ...
- 爬虫入门(五)抓取网页数据
前面已经实现了获取整个网页HTML的功能,并且在获取HTML的基础上,加上一些诸如:下载出错自动重试.用户代理.服务器代理.爬取深度.避免重爬.id遍历.链接遍历等进阶功能.而且在处理过程中也初步使用 ...
最新文章
- Word遇到问题需要关闭
- VMware View 5.0从菜鸟到高手系列 10 –远程图形工作站配置篇
- SmartSVN11 Mac版 注册码序列号
- 把报表的数据导出Excel
- 同事把 Redis用成这鬼样子,真坑!
- 阿里云Spark Shuffle的优化
- php排序算法有哪些,PHP常见的几种排序算法
- WBOLT 搜索推送管理插件(原百度推送管理插件) 3.4.11 Pro
- 如何将网页实现变灰效果?
- SitePoint播客#114:在WordCamp Raleigh上直播第1部分
- C语言格式化输出日期时间
- 中望CAD的引线标注格式怎么改_大神总结:CAD设计五个段位 你在哪个阶段?
- 苹果App Store商店中国区如何改为美国区
- Postgresql忘记密码,如何重置密码
- android圆形的ImageView
- [转]手机游戏六大渠道评测标准大合集
- 使用iperf工具,用java的swing,编写网络带宽监测小工具
- 6. 大尾数法或小尾数法
- 使用代码给ACCESS窗体中32个文本框赋不同值的实例
- 【SpringBoot入门】SpringBoot的配置
热门文章
- 经验:几个985/211/普通院校的本科生/研究生高薪大数据学习全程记录,笔记心得,求职面试
- 数字政府智慧政务一网通办解决方案2022(ppt可编辑)
- 意大利品质至上的菜 自由自在享受美味
- 从零开始的Linux学习日志(3)
- 鼎信通达网关云服务器注册,鼎信通达语音网关 | FreePBX-世界上最大的企业IPPBX开源项目, 支持SIP,PSTN,分机呼叫,队列,电话录音,振铃组等...
- MongoDB 批量写操作
- Linux下如何做整个硬盘的备份
- 将迅雷集成进XP安装光盘(上)(转)
- 信息安全保证人员CISAW-安全集成
- QLineEdit 判断是否为用户输入