你想批评指点四周风景,你首先要爬上屋顶。

0%

  最近在看计算机网络的一些内容,看完着实觉得自己当初学习这门课程的时候,划水划得厉害,一点都没有深入的去理解和思考,虽然现在也还是不够深入….随手整理了一些小的知识点,这里虽然标题带了个一,但也有可能是最后一篇,感觉项目好像做不下去了….虽然还没开始,唉。

  1. 路由器实现了网关的功能,路由器基于ip协议。

  2. 以太网协议实现了局域网内部的计算机之间的通信,但是多个局域网之间无能为力,ip协议实现了局域网之间的通信,但是可能存在丢包的现象(缓存满了,新的数据包丢失),而且通信是主机对主机,tcp保证了通信的完整性和可靠性,防止丢包,通信是进程对进程。

  3. tcp数据包的编号,SEQ。第一个包的编号是一定基础上生成的一个随机数(还记得当初阿里面试的时候被问过这个题,当时依稀记得在哪里看过是个随机数),假设为1,第一个包的长度为100,那么第二个包的编号为101,所以由一个数据包可以知道当前数据包和下一个数据包的编号,接收方也就便于还原。

  4. 确认消息ACK。ACK包含两部分信息,一是期待要收到的下一个数据包的编号,比如当发送方seq=1,length=100,此时接收方ack=101,对前面100字节进行确认,并期待收到101开头的数据包;二是当前接收方接收窗口的剩余容量。

  5. 重发机制:由上述我们知道,ACK会包含期待的下一个数据包的编号,当接受方没有收到期待的编号的数据包,会停在这个编号,不会增加,当发送方发现连续收到了三个相同的ACK,或者超时没有收到ACK,会重发ACK期待的数据包。

  最近在看网络编程的一些东西,偶然看到有一篇文章将“在浏览器中输入 www.baidu.com 后,浏览器和服务器之间的通信过程”作为一个举例,想到了一道比较经典的面试题(朋友在面阿里后端一面的时候问过),就是我们在浏览器输入 www.baidu.com 点击enter后,到浏览器显示百度的主页,这个过程到底发生了什么。
  ps:笔者也是作为一个学习者的角度来按照自己的理解进行一些解读。
  整个的环境就是,我们平时的一个局域网中的一台电脑,来访问百度的主页,主要过程如下:

  1. 打开浏览器在地址栏输入 www.baidu.com ,说明浏览器想要给百度发送一个网页请求的数据包。
  2. 浏览器通过DNS域名解析服务器(在本地)将域名解析为对应的IP地址。
  3. 判断这个ip是不是和本机在同一子网,这里需要用到子网掩码,本机分别将两个ip地址(本机ip和百度ip)做一个and运算,看结果是否是一样,是->局域网内通信,直接tcp连接,不是->跨局域网通信,通过网关进行连接。
  4. 比较发现不属于同一子网,因此数据包需要通过网关进行转发(即本机将请求转发给网关,网关转发给百度服务器,百度服务器的响应结果返回给网关,网关再转发给本机)。
  5. 通过ARP协议获得 www.baidu.com 的ip对应的mac地址,通过mac地址和ip地址就确定了要建立通信的对象。
  6. 网关和百度服务器三次握手建立TCP连接。
  7. 百度服务器收到请求,返回网页的html。
  8. 网关将响应结果转发给相应的主机的浏览器。
  9. 浏览器解析html,请求网页中需要的各种资源。
  10. 浏览器获得请求的资源,对html进行渲染。
  11. 显示百度的首页。

  大致上是这么个过程。
  这里需要解释一下一个问题:
  为什么区分私网(局域网)和公网(广域网)以及网关怎么知道将消息转发给哪一台主机?
  首先公网IP是有限的,而且是收费的,全球这么多设备要上网,每台设备一个IP肯定是不够的,因此在一个局域网中,可以多个设备共用一个公网IP,每台设备又有一个子网IP。这就相当于,全球每个人需要住一个房子是不够的,我们可以安排一家人住一个房子,每个人住一个房间,他们共享一个家庭住址,每个人又有自己的房间地址。在局域网内通信可以直接使用设备子网IP,因为这个IP是大家都知道的,就像房子中你知道上楼左转是哥哥的房间,右转是姐姐的房间一样,但是不同子网之间是不能使用这个IP的,因为这个左转和右转,仅仅是局限于你们家的房子,别人家的房子构造是不一样的,这时候我们就需要通过网关来进行通信,你可以理解成房子与房子之间的通信,使用住址进行通信,假设只有爸爸知道房子的住址,可以和其他房子进行通信,这样你就可以通过爸爸发消息给你的好朋友小明,(这里的你和小明分别是两个子网中的两台主机,而爸爸相当于网关),这样我们就实现了跨子网(房子)的通信,但是你把消息发给小明,小明给你回信之后,爸爸怎么知道这个信是给谁的呢(也就是网关怎么知道这个消息应该转发给哪一台主机),这里使用端口映射来进行区分。我们只需要将设备ip+端口,映射为网关ip+端口即可。
  举例:

设备名 IP
网关 192.168.1.1
设备A 192.168.1.2
设备B 192.168.1.3
设备C 192.168.1.4

  端口映射后:

源ip:端口 映射之后的ip:端口
A:192.168.1.2:60 192.168.1.1:80
B:192.168.1.3:60 192.168.1.1:90
C:192.168.1.4:60 192.168.1.1:100

  这样我们就可以知道,网关80端口来的消息要转发给设备A的60端口,依次类推。也就实现了局域网共用一个公网IP的方式。

  最近在看爬虫,跟着Scrapy的官方文档实例走了一遍,等自己想爬别的网站的时候,发现还是有点问题,于是网上找了个教程,自己跟着做了一遍,然后换了一个网站,爬一下别的数据,现在做一下记录,由于也是刚刚接触,所以在一些使用上可能还存在误区,欢迎大家批评指正。
  http://www.weather.com.cn/weather/101250101.shtml
  这是我们爬取信息的网址,爬取长沙未来七天的天气情况。

  环境:windows10,python3.6,scrapy1.8,anaconda,chorme

创建scrapy项目并生成相应的文件

  首先选择一个你的项目位置,然后在该位置下打开cmd,执行 scrapy start testSpider ,初始化一个scrapy项目,其中最后一个字段是项目名称,效果如下:

  在PyCharm中可以查看一下目录结构:

  这些文件的主要作用在官方文档里都有介绍。
  然后我们回到cmd,根据提示进行操作,cd testSpider 切换到项目的文件夹下,执行 scrapy genspider example example.com,这里example是你的爬虫的name,是他的唯一标示,不同的爬虫的name必须不同,example.com是允许爬取的域。
  我们执行 scrapy genspider weather weather.com.cn 创建一个爬虫的执行文件。执行完之后可以PyCharm中看到在spiders的文件夹下生成了一个weather.py文件:

  文件包含一些自动生成的代码。

分析需要爬取的网页并编码

  我们打开那个网址,ctrl+shift+i,检查,一步一步找到我们需要的信息,最终发现,这些天气的信息都在一个如图所示的位置。

  找到这个位置之后,我们点开一天的,信息如下图所示,因为我是在晚上写的这篇博客,看的又是第一天,所以只有最低温度,没有最高温度,我们提取 天,天气,最低温和最高温这4项信息。

  这时候,我们需要打开项目中的items.py,写一个类来保存(封装)我们的这些数据,如下图所示。

  下面需要我们的爬虫登场了,打开spider下的weather.py,我们下面使用BeautifulSoup来进行数据的提取。我直接贴上代码喽。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import scrapy
from bs4 import BeautifulSoup
from weatherSpider.items import WeatherItem

class WeahterSpider(scrapy.Spider):
name = 'weather' #spider的名字,唯一标志
allowed_domains = ['weather.com.cn'] #允许爬取的域
start_urls = ['http://www.weather.com.cn/weather/101250101.shtml'] #开始爬取的起点

def parse(self,response):
html = response.text #获得爬到的网页的HTML代码

soup = BeautifulSoup(html,'lxml') #创建一个soup对象
weather = WeatherItem() #创建一个weatherItem对象,存储爬取的信息
div_7d = soup.find('div',class_='c7d') #找到class为c7d的标签
if div_7d is not None: #如果存在
ul = div_7d.find('ul') #逐步缩小范围
if ul is not None:
for li in ul.find_all('li'):
if li is not None:
weather['day'] = li.find('h1').get_text() #取标签包含的数据
weather['wea'] = li.find('p').get_text()
span = li.find('span')
if span is not None:
weather['highest'] = span.get_text()
weather['lowest'] = li.find('i').get_text()
print(weather)

  整体的思想就是一步一步缩小范围,逐步获得我们需要的数据。

entryPoint.py 便捷启动

  编写完上面的代码,在scrapy项目的根目录下执行 scrapy crawl weather 就能为了能够运行爬虫程序了,但是为了更加方便的启动爬虫,我们可以在项目根目录下编写一个entrypoint.py文件,直接在PyCharm中启动爬虫,

1
2
3
from scrapy.cmdline import execute

execute(['scrapy','crawl','weather'])

  执行之后就能够看到爬取的数据的结果了:

  到这,这个简单的scrapy爬虫实战就结束了….确实很简单,但也会有成就感。

补充

  最后补充一点,菜鸡用markdown的时候,#后面忘记加空格,导致标题显示不出来,嘿嘿嘿,抽自己一下。

  报错如下:

  但是我已经在站点配置文件配置好,并且已经在coding的项目中添加了公钥,但是请求连接时还是出现了问题。
  解决办法:

1
2
3
4
1.执行   eval `ssh-agent`
2.执行 ssh-add ~/.ssh/rsa
3.执行 ssh-add –l
4.重新尝试连接 ssh -T git@e.coding.net

  之前一直使用的 ssh -T git@git.coding.net 结果执行完上面三个指令还是连接不上,后来在Coding的官方文档中看到这个

  原来是连接指令错误….
  这样就成功连接了。

hexo g 执行后不生成index.html

  这里也只是提出几种可能性:

  • 我当时执行 npm install 之后重新执行一遍就可以了
  • 朋友发现自己多包含了一个头文件

修改背景图片

  next主题更新后,就没有了custom.styl文件,当时网上很多教程都是使用这个文件设置背景图片,但是新版本的next也提供了用户自定义的文件,首先需要在next主题的配置文件中启用:

1
2
3
4
5
6
7
8
9
10
11
custom_file_path:
#head: source/_data/head.swig
#header: source/_data/header.swig
#sidebar: source/_data/sidebar.swig
#postMeta: source/_data/post-meta.swig
#postBodyEnd: source/_data/post-body-end.swig
#footer: source/_data/footer.swig
#bodyEnd: source/_data/body-end.swig
#variable: source/_data/variables.styl
#mixin: source/_data/mixins.styl
style: source/_data/styles.styl

  将最后一个的注释取消,然后到blog的source文件夹下(注意,是blog的source,不是next的source)创建这个文件,将设置背景图片的css放进去,

1
2
3
4
5
6
7
body {
background-image:url(/images/header.jpg);
background-repeat: no-repeat;
background-attachment:fixed;
background-position:50% 50%;
background-size:cover;
}

  还有注意将图片放在next的source的images中,至于为什么这么迷我也不清楚….
  这里顺便说一下,设置背景透明度的css也直接放在这个文件中就可以了,透明度的效果可以根据自己的喜好调节,1是不透明,0是全透明,我是小透明,不是很聪明。

1
2
3
 .main-inner { 
opacity: 0.9;
}

点击头像回到主页

  确实哈,鼠标放在头像上就想去点,虽然卵用不大,但这个功能必须得有啊。
  网上教程用不了,在sidebar.swig文件中没有头像的标签,于是我就把附近的文件找了找,反正思路就是加个跳转,管他在哪里,只要能找到,加上看他跳不跳。
  终于,在\next\layout_partials\sidebar下找到了site-overview.swig文件,找到

1
<img class="site-author-image" itemprop="image" alt="{{ author }}" src="{{ url_for(theme.avatar.url or theme.images + '/header.jpg') }}">

  在这段代码的开始前面和结束后面分别加上第一行和第二行:

1
2
<a href="/">
</a>

  记得将img标签的src改成自己头像路径。