-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
170 lines (170 loc) · 51.5 KB
/
search.xml
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[用Charles对Http请求进行抓取]]></title>
<url>%2F2018%2F12%2F06%2F%E7%94%A8Charles%E5%AF%B9Http%E8%AF%B7%E6%B1%82%E8%BF%9B%E8%A1%8C%E6%8A%93%E5%8F%96%2F</url>
<content type="text"><![CDATA[Charles 是在 Mac 下常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。 Charles 通过将自己设置成系统的网络访问代理服务器,使得所有的网络访问请求都通过它来完成,从而实现了网络封包的截取和分析。 除了在做移动开发中调试端口外,Charles 也可以用于分析第三方应用的通讯协议。配合 Charles 的 SSL 功能,Charles 还可以分析 Https 协议。 Charles 是收费软件,可以免费试用 30 天。试用期过后,未付费的用户仍然可以继续使用,但是每次使用时间不能超过 30 分钟,并且启动时将会有 10 秒种的延时。因此,该付费方案对广大用户还是相当友好的,即使你长期不付费,也能使用完整的软件功能。只是当你需要长时间进行封包调试时,会因为 Charles 强制关闭而遇到影响。 Charles 主要的功能包括: 截取 Http 和 Https 网络封包。 支持重发网络请求,方便后端调试。 支持修改网络请求参数。 支持网络请求的截获并动态修改。 支持模拟慢速网络。 Charles 4 新增的主要功能包括: 支持 Http 2。 支持 IPv6。 安装Charles 官网安装,速度有点慢 设置系统代理 打开Proxy选项,选中其中的macOS proxy,打开系统代理 在Chrome浏览器中是默认不使用系统代理的,需要在Chrome里手动设置,或者安装一个Chrome插件:SwitchyOmega 。在上面设置一个charles的情景模式,如下图: Charles的主界面 页面有Structure和Sequence两种显示模式。 Structure 视图将网络请求按访问的域名分类。 Sequence 视图将网络请求按访问的时间排序,Sequence类似于Chrome的开发者模式。 对于显示在界面上的网页请求,可以在Filter中进行简单的筛选 筛选页面设置 在主界面Filter中输入需要筛选的网页 在Charles的菜单选项中选择Proxy->Recording Settings,然后选择Inlcude栏,Add你需要添加的网站。 在想要过滤的网页右键选择Focus,后在Filter栏右边勾选Focused项。 抓取https信息 安装证书如果没有设置这一步的话,你是抓取不到https信息的,如果需要截取分析Https协议相关的内容,就需要安装Charles的CA证书。 在Charles顶部菜单栏中选择Help,在选择SSL Proxying - > Install Chrales Root Certificate 在系统的KeyClain中将Charles的证书选为信任 设置某个网站或者所有网站都默认截取HTTPS请求,在SSL Proxyingz Settings中设置,Add一个新的规则。 修改GET请求的参数在上面已经设置好了之后,就可以对抓取到的Http请求进行改包,以百度为例,可以看出,搜索的内容就是在GET方法中的wd属性的值来决定的。 所以我们给这个请求标记一个breakpoints,在Charles主界面enable breakpoints,然后Command + R刷新页面,页面请求会先经过Charles,再返回到浏览器中,可以看到目前搜索了一串字符test,将其改为测试,点击Execute,继续执行接受下一个请求,最后可以看到百度的结果为后面修改的内容。]]></content>
<categories>
<category>实用工具</category>
</categories>
<tags>
<tag>Http</tag>
<tag>Charles</tag>
</tags>
</entry>
<entry>
<title><![CDATA[MacOS下设置 iTerms & Oh-My-Zsh]]></title>
<url>%2F2018%2F12%2F06%2FMacOS%E4%B8%8B%E8%AE%BE%E7%BD%AE%20iTerms%20%26%20Oh-My-Zsh%2F</url>
<content type="text"><![CDATA[Introduce oh-my-zshzsh 是一个强大的 bash 替代,而oh-my-zsh是 zsh 的一个傻瓜化配置工具。 iTerms 2替换Terminal,在Terminal基础上加了新特性功能。 solarized一款主题,可以更换iterms的配色。 Install iTerms 2直接从官网下载打开就行,弹出的两个对话框都选择默认即可。 oh-my-zsh 需要先安装zsh(版本需要v4.3.9或更高) 安装zsh主要用两种方法: 使用包管理器安装,例如sudo apt-get install zsh 源码安装,下载地址 需要安装curl或wget 需要安装git via curl1sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" via wget1sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)" 安装完后出现信息 设置自动提示命令 克隆仓库到本地 ~/.oh-my-zsh/custom/plugins 路径下 1git clone git://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions 用 vim 打开 .zshrc 文件,找到插件设置命令,默认是 plugins=(git) ,我们把它修改为 1plugins=(zsh-autosuggestions git) 重新打开终端窗口 调好之后可能会遇到提示的词不够清晰,可以将其调亮: 移动到 ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions 路径下 12> `cd` `~/.oh-my-zsh``/custom/plugins/zsh-autosuggestions`> 用 vim 打开 zsh-autosuggestions.zsh 文件,修改 ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=’fg=10’。 语法高亮 macOS需要先安装brew 在terminal中输入/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install*)"* 使用homebrew安装 zsh-syntax-highlighting 插件。 1brew install zsh-syntax-highlighting 配置.zshrc文件,插入一行。 1source /usr/local/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 输入命令 1source ~/.zshrc 至此,所有配置都完成了。]]></content>
<categories>
<category>实用工具</category>
</categories>
<tags>
<tag>Mac</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Python中的生成器和yield语句]]></title>
<url>%2F2018%2F10%2F24%2Fyield%2F</url>
<content type="text"><![CDATA[yield表达式在Python的使用中非常广泛,最近在做爬虫项目的时候经常有用到。yield在函数中的功能类似于return,不同的是yield每次返回结果之后函数并没有退出,而是每次遇到yield关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。如果一个函数需要多次循环执行一个动作,并且每次执行的结果都是需要的,这种场景很适合使用yield实现。 在Python文档中,对于yield表达式的描述为 yield 表达式仅在定义generator函数时使用,因此只能用在函数定义的函数体中。在函数体中使用 yield 表达式会使该函数成为 generator。 当调用 generator 函数时,它会返回一个 iterator,同时又是一个 generator。然后,generator 控制 generator 函数的执行。当一个生成器的方法被调用时执行开始。此时,执行进行到第一个yield表达式,在那里它被再次挂起,将expression_list的值返回给生成器的调用者。挂起,我们的意思是保留所有局部状态,包括局部变量的当前绑定,指令指针,内部计算栈和任何异常处理的状态。当通过调用其中一个生成器的方法来恢复执行时,函数可以像yield表达式只是另一个外部调用一样继续进行。恢复后的yield表达式的值取决于恢复执行的方法。如果使用__next__()(通常通过for或next()内置函数),则结果为None。否则,如果使用send(),则结果将是传递到该方法的值。 其中提到了两个在Python比较重要的类型,generator和iterator,生成器和迭代器,在弄懂生成器之前,先来了解一下迭代器。 迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。 迭代器有两个基本的方法:iter() 和 next()。 字符串,列表或元组对象都可用于创建迭代器: 123456>>>list=[1,2,3,4]>>> it = iter(list) # 创建迭代器对象>>> print (next(it)) # 输出迭代器的下一个元素1>>> print (next(it))2 关于迭代器,我们只要了解最关键的地方在于它的__iter__()与 __next__()方法。 __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了__next__() 方法并通过 StopIteration 异常标识迭代的完成。 __next__()方法(Python 2 里是 next())会返回下一个迭代器对象。 下面再来回到关于生成器,简单理解迭代器和生成器的关系其实是包含,生成器能做到的事,迭代器也能做到,生成器是一种可以简单有效的创建迭代器的工具。生成器在需要返回数据时使用yield语句,每个yield返回一个generator iterator的函数,记住执行的位置和状态(包括局部变量和等待的 try 语句)。当generator iterator恢复时,即对它调用next()时,它从离开的位置重新开始(与函数不同,函数每次调用从起始开始,并会记住所有的数据值和上次执行的语句)。 1234567891011121314151617181920212223>>> def echo(value=None):... print("Execution starts when 'next()' is called for the first time.")... try:... while True:... try:... value = (yield value)... except Exception as e:... value = e... finally:... print("Don't forget to clean up when 'close()' is called.")...>>> generator = echo(1)>>> print(next(generator))Execution starts when 'next()' is called for the first time.1>>> print(next(generator))None>>> print(generator.send(2))2>>> generator.throw(TypeError, "spam")TypeError('spam',)>>> generator.close()Don't forget to clean up when 'close()' is called. more… Specification: Try/Except/FinallyAs noted earlier, yield is not allowed in the try clause of a try/finally construct. A consequence is that generators should allocate critical resources with great care. There is no restriction on yield otherwise appearing in finally clauses, exceptclauses, or in the try clause of a try/except construct: 12345678910111213141516171819202122232425> >>> def f():> ... try:> ... yield 1> ... try:> ... yield 2> ... 1/0> ... yield 3 # never get here> ... except ZeroDivisionError:> ... yield 4> ... yield 5> ... raise> ... except:> ... yield 6> ... yield 7 # the "raise" above stops this> ... except:> ... yield 8> ... yield 9> ... try:> ... x = 12> ... finally:> ... yield 10> ... yield 11> >>> print list(f())> [1, 2, 4, 5, 8, 9, 10, 11]>]]></content>
<categories>
<category>Python</category>
</categories>
<tags>
<tag>Python</tag>
</tags>
</entry>
<entry>
<title><![CDATA[HTTP协议中的GET和POST方法]]></title>
<url>%2F2018%2F10%2F22%2Fget-post%2F</url>
<content type="text"><![CDATA[两种最常用的 HTTP 方法是:GET 和 POST。 什么是HTTP 超文本传输协议(HTTP)的设计目的是保证客户机和服务器之间的通信。 HTTP的工作方式是客户机与服务器之间的请求-应答协议 web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。 GET方法在get方法中,查询字符串(名称/值对)是在GET请求的URL中发送的,例如: 1https://www.baidu.com/baidu?isource=infinity&iname=baidu&itype=web&tn=98012088_9_dg&ch=7&ie=utf-8&wd=xxxxx 有关 GET 请求的其他一些注释: GET 请求可被缓存 GET 请求保留在浏览器历史记录中 GET 请求可被收藏为书签 GET 请求不应在处理敏感数据时使用 GET 请求只应当用于取回数据 POST方法在post方法中,查询字符串(名称/值对)是在POST请求的HTTP消息主体中发送的 有关 POST 请求的其他一些注释: POST 请求不会被缓存 POST 请求不会保留在浏览器历史记录中 POST 不能被收藏为书签 比较 GET 与 POST下面的表格列出了比较了两种 HTTP 方法的一般理解:GET 和 POST。 GET POST 后退按钮/刷新 无害 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 书签 可收藏为书签 不可收藏为书签 缓存 能被缓存 不能缓存 编码类型 application/x-www-form-urlencoded application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 历史 参数保留在浏览器历史中。 参数不会保存在浏览器历史中。 对数据长度的限制 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 无限制。 对数据类型的限制 只允许 ASCII 字符。 没有限制。也允许二进制数据。 安全性 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET ! POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 可见性 数据在 URL 中对所有人都是可见的。 数据不会显示在 URL 中。 上图中,http协议对于URL长度其实是没有限制的,只是Web服务器和浏览器对URI都有自己的长度限制 服务器的限制:接触的最多的服务器类型就是Nginx和Tomcat,对于url的长度限制是通过控制http请求头的长度来进行限制的,nginx的配置参数为large_client_header_buffers,tomcat的请求配置参数为 maxHttpHeaderSize。 浏览器的限制:每种浏览器也会对url的长度有所限制。 其他 HTTP 请求方法下面的表格列出了其他一些 HTTP 请求方法: 方法 描述 HEAD 与 GET 相同,但只返回 HTTP 报头,不返回文档主体。 PUT 上传指定的 URI 表示。 DELETE 删除指定资源。 OPTIONS 返回服务器支持的 HTTP 方法。 CONNECT 把请求连接转换到透明的 TCP/IP 通道。 深入了解GET和POST方法首先先来了解RFC: 征求意见稿(英语:Request For Comments,缩写为RFC),是由互联网工程任务组(IETF)发布的一系列备忘录。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件,以编号排定。目前RFC文件是由互联网协会(ISOC)赞助发行。 然后在来了解一下「语法」和「语义」semantic 的关系 一种语言是合法句子的集合。什么样的句子是合法的呢?可以从两方面来判断:语法和语义。语法是和文法结构有关,然而语义是和按照这个结构所组合的单词符号的意义有关。合理的语法结构并不表明语义是合法的。例如我们常说:我上大学,这个句子是符合语法规则的,也符合语义规则。但是大学上我,虽然符合语法规则,但没有什么意义,所以说是不符合语义的。 语义则定义了这一类型的请求具有什么样的性质。比如GET的语义就是「获取资源」,POST的语义是「处理资源」,那么在具体实现这两个方法时,就必须考虑其语义,做出符合其语义的行为。 当然在符合语法的前提下实现违背语义的行为也是可以做到的,比如使用GET方法修改用户信息,POST获取资源列表,这样就只能说这个请求是「合法」的,但不是「符合语义」的。 写到这里突然联想到XML里面的两个概念:Well Formed和Valid,似乎也正是语法和语义的理念呢。 上文说到方法是请求语义的主要来源,也即是还有次要来源,一些请求Header可以进一步修饰请求的语义,比如一个带上了 Range Header的GET请求就变成了部分请求。 RFC7231里紧接着定义了HTTP方法的几个特性: Safe - 安全这里的「安全」和通常理解的「安全」意义不同,如果一个方法的语义在本质上是「只读」的,那么这个方法就是安全的。客户端向服务端的资源发起的请求如果使用了是安全的方法,就不应该引起服务端任何的状态变化,因此也是无害的。 此RFC定义,GET, HEAD, OPTIONS 和 TRACE 这几个方法是安全的。但是这个定义只是规范,并不能保证方法的实现也是安全的,服务端的实现可能会不符合方法语义,正如上文说过的使用GET修改用户信息的情况。引入安全这个概念的目的是为了方便网络爬虫和缓存,以免调用或者缓存某些不安全方法时引起某些意外的后果。User Agent(浏览器)应该在执行安全和不安全方法时做出区分对待,并给用户以提示。 Idempotent - 幂等幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同。按照RFC规范,PUT,DELETE和安全方法都是幂等的。同样,这也仅仅是规范,服务端实现是否幂等是无法确保的。引入幂等主要是为了处理同一个请求重复发送的情况,比如在请求响应前失去连接,如果方法是幂等的,就可以放心地重发一次请求。这也是浏览器在后退/刷新时遇到POST会给用户提示的原因:POST语义不是幂等的,重复请求可能会带来意想不到的后果。 Cacheable - 可缓存性 顾名思义就是一个方法是否可以被缓存,此RFC里GET,HEAD和某些情况下的POST都是可缓存的,但是绝大多数的浏览器的实现里仅仅支持GET和HEAD。关于缓存的更多内容可以去看RFC7234。 在这三个特性里一直在强调同一个事情,那就是协议不等于实现:协议规定安全在实现里不一定安全,协议规定幂等在实现里不一定幂等,协议规定可缓存在实现里不一定可缓存。 GET的语义是请求获取指定的资源。GET方法是安全、幂等、可缓存的(除非有 Cache-Control Header的约束),GET方法的报文主体没有任何语义。 POST的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST不安全,不幂等,(大部分实现)不可缓存。 参考文章: HTTP协议中GET和POST方法的区别 HTTP 方法:GET 对比 POST]]></content>
<categories>
<category>计算机网络</category>
</categories>
<tags>
<tag>HTTP</tag>
</tags>
</entry>
<entry>
<title><![CDATA[用scrapy爬取伯乐在线的文章]]></title>
<url>%2F2018%2F10%2F20%2F%E7%94%A8scrapy%E7%88%AC%E5%8F%96%E4%BC%AF%E4%B9%90%E5%9C%A8%E7%BA%BF%E7%9A%84%E6%96%87%E7%AB%A0%2F</url>
<content type="text"><![CDATA[简单记录一下自己在linux环境下使用scrapy爬取伯乐在线并提取结构性数据到数据库中的过程 项目环境 deepin15.7 + python 3.6 + mysql 5.5 + pycharm 搭建环境 安装python环境 安装pip 安装mysql 安装scrapy,virtualenv pip源推荐使用清华大学镜像源 https://pypi.tuna.tsinghua.edu.cn/simple 创建scrapy项目在pycharm中创建一个虚拟环境,安装好环境后,在目录下面创建scrapy项目 1scrapy startproject ArticleSpider 项目的结构如下 1234567891011├── ArticleSpider│ ├── items.py│ ├── middlewares.py│ ├── pipelines.py│ ├── __pycache__│ ├── settings.py│ ├── spiders│ │ ├── __init__.py│ │ ├── jobbole.py│ │ └── __pycache__└── scrapy.cfg 分析网站中文章页面结构先进入伯乐在线网站http://www.jobbole.com/,然后随便点开一篇文章 例如http://blog.jobbole.com/114297/ 对于某一篇文章,目前只需要获得文章的评论数,收藏数,点赞数(默认为1),分类,标题,正文,文章封面图和文章链接。 在Chrome中按F12查看个元素的标签,例如文章的收藏数 在scrapy shell中获取网页数据scrapy提供了一个shell环境方便我们调试,并查看获取的元素是否正确 在venv目录的bin目录下 1source activate 进入venv环境后输入 1scrapy shell http://blog.jobbole.com/114297/ 进入到shell后用css选择器或xpath选择器选取刚才要获得的元素 12>>> response.css('.bookmark-btn::text').extract()[' 18 收藏'] 获得的是一个列表,因为class为bookmark-btn的元素只有一个,所以将上面的extract()改为extract_first(‘’) 12>>> response.css('.bookmark-btn::text').extract_first()' 18 收藏' 得到一个字符串,这时将其中的18用正则表达式提取出来后就可以获取到收藏数了,其他的也是如此 编写代码从pycharm中启动项目首先在项目根目录中打开命令行,创建爬虫文件 1scrapy genspider jobbole www.jobbole.com 然后打开main文件 12345678from scrapy.cmdline import executeimport sysimport ossys.path.append(os.path.dirname(os.path.abspath(__file__)))execute(['scrapy', 'crawl', 'jobbole']) 在main文件中只有两行执行的代码, 1sys.path.append(os.path.dirname(os.path.abspath(__file__))) 是将当前的main文件所在目录,即根目录将入环境中,就可以调用别的py文件的方法和类 1execute(['scrapy', 'crawl', 'jobbole']) 在第一行导入了scrapy.cmdline即scrapy命令行工具的execute方法,因为Scrapy是通过 scrapy 命令行工具进行控制的。 这里我们称之为 “Scrapy tool” 以用来和子命令进行区分。 对于子命令,我们称为 “command” 或者 “Scrapy commands”。上面代码即相当于执行了scrapy crawl jobbole 获取url在jobbole.py中,其中的parse函数用来获取当前页中的所有文章url和下一页的url 1234567891011121314151617class JobboleSpider(scrapy.Spider): name = 'jobbole' allowed_domains = ['blog.jobbole.com'] start_urls = ['http://blog.jobbole.com/all-posts/'] ''' 提取当前页所有文章的url 一页20个 并获取下一页的url ''' def parse(self, response): res_nodes = response.css('.post.floated-thumb .post-thumb a') for post_node in res_nodes: image_url = post_node.css('img::attr(src)').extract_first('') post_url = post_node.css('::attr(href)').extract_first('') yield Request(url=parse.urljoin(response.url, post_url), meta={'front_image_url':image_url}, callback=self.parse_detail) next_url = response.css('.next.page-numbers::attr(href)').extract_first('') if next_url: yield Request(url=parse.urljoin(response.url, next_url), callback=self.parse) 通过itemloader装载items在scrapy中提供Item类,Item对象是种简单的容器,保存了爬取到得数据。 其提供了类似于词典(dictionary-like)的API以及用于声明可用字段的简单语法。 如果直接用Item类,如果后期要对代码进行维护就会变得很繁琐,使用ItemLoader类就可以自己编写函数来处理item中的数据,在jobbole.py中加入Item 123456789101112res_image_url = response.meta.get('front_image_url', '')item_loader = ArticleItemLoader(item=JobBoleArticleItem(), response=response)item_loader.add_css('title', '.entry-header h1::text')item_loader.add_value('url', response.url)item_loader.add_value('url_md5', get_md5(response.url))item_loader.add_css('create_date', 'p.entry-meta-hide-on-mobile::text')item_loader.add_value('front_image_url', [res_image_url])item_loader.add_css('comments_nums', 'a[href="#article-comment"] span::text')item_loader.add_css('tags', '.entry-meta-hide-on-mobile a::text')item_loader.add_css('content', 'div.entry')item_loader.add_css('collection_nums', '.bookmark-btn::text')item_loader.add_css('praise_nums', '.vote-post-up h10::text') Input and Output processorsItem Loader在每个(Item)字段中都包含了一个输入处理器和一个输出处理器。 输入处理器收到数据时立刻提取数据 (通过 add_xpath(), add_css() 或者 add_value() 方法) 之后输入处理器的结果被收集起来并且保存在ItemLoader内. 收集到所有的数据后, 调用 ItemLoader.load_item() 方法来填充,并得到填充后的 Item 对象. 这是当输出处理器被和之前收集到的数据(和用输入处理器处理的)被调用.输出处理器的结果是被分配到Item的最终值。 之后在Item.py中加入 123456789101112131415161718192021222324class JobBoleArticleItem(scrapy.Item): title = scrapy.Field() create_date = scrapy.Field( input_processor=MapCompose(date_convert) ) url = scrapy.Field() url_md5 = scrapy.Field() front_image_url = scrapy.Field( output_processor=MapCompose(return_value) ) front_image_path = scrapy.Field() praise_nums = scrapy.Field( input_processor=MapCompose(get_nums) ) comments_nums = scrapy.Field( input_processor=MapCompose(get_nums) ) tags = scrapy.Field( output_processor=Join(',') ) content = scrapy.Field() collection_nums = scrapy.Field( input_processor=MapCompose(get_nums) ) 然后在settings.py中,将robots.txt规则设置为False 1ROBOTSTXT_OBEY = False 这时爬虫项目大致完成,接下来配置数据库和pipelines 写入数据库首先需要安装python的mysql-dev,在这里记录一下我遇到的坑,在linux下直接pip install mysql-python会出现错误,这时需要在外面打开命令行,执行sudo apt-get install libmysqlclient-dev后就可以安装了。 写入数据库有同步和异步的方法,这里只记录异步方法,因为同步方法出错让我卡了两个小时,爷吐了 12345678910111213141516171819202122232425262728293031323334class MysqlTwistedPipline(object): def __init__(self, dbpool): self.dbpool = dbpool @classmethod def from_settings(cls, settings): dbparms = dict( host = settings["MYSQL_HOST"], db = settings["MYSQL_DBNAME"], user = settings["MYSQL_USER"], passwd = settings["MYSQL_PASSWORD"], charset='utf8', cursorclass=MySQLdb.cursors.DictCursor, use_unicode=True, ) dbpool = adbapi.ConnectionPool("MySQLdb", **dbparms) return cls(dbpool) def process_item(self, item, spider): # 使用twisted将mysql插入变成异步执行 query = self.dbpool.runInteraction(self.do_insert, item) query.addErrback(self.handle_error, item, spider) # 处理异常 def handle_error(self, failure, item, spider): # 处理异步插入的异常 print(failure) def do_insert(self, cursor, item): # 执行具体的插入 # 根据不同的item 构建不同的sql语句并插入到mysql中 insert_sql, params = item.get_insert_sql() print(insert_sql, params) cursor.execute(insert_sql, params) 在pipelines.py中如上配置,然后在settings.py的最后面加上数据库帐号密码之类的信息,再在items.py中编写get_insert_sql函数就可以将数据写入到数据库中了,而且不同的爬虫项目还可以复用这个结构,只需要改写get_insert_sql中的sql语句就可以了。 将图片和爬取的数据导出为Json文件懒得写了,放在github上。]]></content>
<categories>
<category>Python</category>
</categories>
<tags>
<tag>Python</tag>
<tag>Scrapy</tag>
<tag>Spider</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Mysql ON DUPLICATE KEY 用法]]></title>
<url>%2F2018%2F10%2F20%2FON%20DUPLICATE%20KEY%20%E7%94%A8%E6%B3%95%2F</url>
<content type="text"><![CDATA[为保证数据表中的内容不会重复,通常会设定一个或多个列为Primary key 首先,我想向表中插入一条数据(假设name为PK) 1INSERT INTO player(name, sex, weight)VALUES('jack', 'male', 50) 在插入这段数据之前,我们会先检查PK值是否已经存在以免发生错误,所以需要多写一段select语法 1SELECT * FROM player WHERE name = 'jack' 如果现在的功能需求是“新增一条数据,如果已经存在就更新” 就可以使用MySQL中的语法 1INSERT ... ON DUPLICATE KEY UPDATE 根据刚才的需求,改写sql语句 1INSERT into player(name, sex, weight)VALUES('jack', 'male', 50) ON DUPLICATE KEY UPDATE name = 'jack', sex = 'male', weight = '50']]></content>
<categories>
<category>数据库</category>
</categories>
<tags>
<tag>mysql</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Visual Works Character Prototype]]></title>
<url>%2F2018%2F09%2F20%2FVISUAL-WORKS%2F</url>
<content type="text"><![CDATA[Fascinate the world with your ideas. Let this character guide you. Youtube: Bilibili:]]></content>
<tags>
<tag>游戏CG</tag>
</tags>
</entry>
<entry>
<title><![CDATA[通过UDP53实现校园网免认证上网]]></title>
<url>%2F2018%2F09%2F17%2F%E9%80%9A%E8%BF%87UDP53%20%E5%AE%9E%E7%8E%B0%E6%A0%A1%E5%9B%AD%E7%BD%91%E5%85%8D%E8%AE%A4%E8%AF%81%E4%B8%8A%E7%BD%91%2F</url>
<content type="text"><![CDATA[11.18更新:开通阿里云学生机轻量服务器可升级为最高5M带宽,每月定额1000G流量,比云服务器ECS要划算。 11.18更新:softether VPN server 端的链接失效了,可以从我的网盘里下载 链接:https://pan.baidu.com/s/1G2wM8JAraYKaP_7QM2_ovA 密码:9xir 下载好之后传到服务器中,后面的步骤一样 一、 前言阿里云的学生服务器买了有一段时间了,本来想拿来部署一个网站的,但是因为国内坑爹的备案制度,导致我又买了一个国外的服务器来部署(国外的学生服务器比国内便宜多了),所以目前阿里云这个服务器就空闲了下来,为了不浪费这个服务器资源,于是就去知乎找了一些有关于学生服务器的用处,就发现有人提了这个用处,而且我们学校 12 点断网后连手机信号也会断,只能通过这种方法来上网,顿时觉得我们学校太 tm 坑了,但这个方法并不适用于所有校园网认证,如需锐捷认证的有线连接,正巧我们学校的还有无线 web 认证, 可能是学校自己弄的 ,总之这个认证系统就很水,这个方法用了一段时间了并没有出任何问题,至于以后就不知道了, 也许网管某天会发现 53 端口走了一堆 malformed packet 然后警告我一波。 二、环境搭建你需要: 一台服务器 阿里云,腾讯云的学生机都可以,甚至 DigitalOcean,Vultr 的国外节点也可以,但由于国外的 vps 使用这个方法时会受到 GFW 的干扰,所以很不稳定,不推荐使用国外节点,但是国外服务器不限带宽还是很爽的。 一台能连接网络的设备 经过试验,pc 端 windows,macbook,linux 都可以,移动端 ios,Android 也没问题,但是管理工具移动端没有。 测试网关一般来说如果是使用的无线网络,无线网关会放行 UDP67/68,也就是 DHCP 端口来获取 ip,和 UDP53(DNS 端口)来获取 DNS,使用如下工具来测试 53 端口是否通行: 项目地址 下载下来之后解压并运行 dist 内的 UDP53.exe。 如果出现的是 congratulations,那就代表 53 端口完全放行,可以使用下面的方法,如果不是的话,就只能通过 DNS 通道来搭建环境,下面不做介绍。 购买服务器 下面都以阿里云服务器为例子 如果你没有服务器,先在阿里云服务器上购买一个学生机,这是我的推广链接 ,注册一个阿里云账号登陆并找到云翼计划,购买一个学生机,系统选择 centOS7,设置登陆密码,然后使用类似 putty 或 secureCRT 的 ssh 工具,远程连接到服务器上。 服务器环境搭建 安装 softether VPN server 使用 ssh 工具连接到 vps 上,先更新 yum 源。 1yum update 输入 y 确认,然后安装依赖库 1yum -y install gcc zlib-devel openssl-devel readline-devel ncurses-devel 如果是 ubuntu 的话,使用的是 apt-get 来作为包管理器。 在当前目录 /root 下载 softether VPN server 端 1wget http://oks2t4o68.bkt.clouddn.com/softether-vpnserver-v4.22-9634-beta-2016.11.27-linux-x64-64bit.tar.gz 解压缩 1tar -zvxf softether-vpnserver-v4.22-9634-beta-2016.11.27-linux-x64-64bit.tar.gz 进入目录并安装 12cd vpnservermake 选项全部选 1 安装完后再当前目录继续输入 1./vpnserver start 开启服务 设置 softether VPN server 服务端 1./vpncmd 依次输入 1,回车,回车,再输入 1ServerPasswordSet 设置服务端密码,到此服务器端已经部署完毕 管理 softether VPN server下面回到 pc 端,以 win10 为例,先从官网下载最新版 https://www.softether-download.com/cn.aspx?product=softether(需翻墙),然后安装管理工具,打开 slmgr.exe 点击新设置 主机名填写你的vps 服务器 ip,输入你刚才设置的密码 将弹出的设置关掉,进入主界面 点击管理虚拟 HUB 再点击管理用户 点击新建 如图设置,用户名和密码自己填 回到管理虚拟 HUB 界面,点击虚拟 NAT 的 DHCP 服务器,启用 SecureNAT 将端口改为 53,并点击为 OpenVPN Client 生成配置样本文件,将其保存到一个地方。 配置 OpenVPN到官网下载 OpenVPN,https://openvpn.net/index.php/open-source/downloads.html(需翻墙,跟 VPN 有关的东西在国内墙得厉害),下载 windows 版并安装,然后打开,点击 Import file 将刚才的样本文件中的以 l3 结尾的文件导入到 OpenVPN 的配置目录中 导入完之后点击 connect 将你刚才设置的虚拟 HUB 中的用户名和密码输入,勾选 Save password,如果出现这个提示,就表示设置成功了 这时你可以注销认证,再试试连接,发现依然可以联网。 三、实际使用阿里云学生服务器自带的带宽是 1M,网速很不理想,最快也就 150K/s 的速度,但是阿里云可以通过暂时提升带宽来提升网速,总的来说就是服务器的带宽决定了我们的网速,下面是 10M 的速度作为参考。。。 如果没有特殊的需求的话,看看普通网页的话 1M 的速度够了,主要是可以解决 12 点后完全没网的尴尬。 参考文章 UDP 53 免费上网、DNS 隧道经验谈 SoftEther VPN Server 安装笔记 + 福利 Centos7.4 使用 SoftEther 搭建 VPN]]></content>
<categories>
<category>计算机网络</category>
</categories>
<tags>
<tag>校园网</tag>
<tag>Linux</tag>
<tag>服务器</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux教程]]></title>
<url>%2F2018%2F09%2F10%2FLinux%E6%95%99%E7%A8%8B%2F</url>
<content type="text"><![CDATA[第 2 章 新手必须掌握的 Linux 命令 man命令中常用按键以及用途 man命令帮助信息的结构以及意义 举例:man man 常用系统工作命令 echo 输出字符串或变量的值。 date 用于显示及设置系统的时间或日期。date [选项] [+指定的格式] 其中+可以格式化。 参数列表: 举例:date "+%Y-%m-%d %H:%M:%S" reboot 重启系统 poweroff 关闭系统 wget 用于在终端中下载网络文件 参数列表: 举例:wget https://www.linuxprobe.com/docs/LinuxProbe.pdf ps 用于查看系统中的进程状态 参数列表: 在 Linux 系统中,有5中常见的进程状态,分别为运行,中断,不可中断,僵死与停止,其各自含义如下所示。 进程状态各列的含义: 1在Linux系统中的命令参数有长短格式之分,长格式和长格式之间不能合并,长格式和短格式之间也不能合并,但短格式和短格式之间是可以合并的,合并后仅保留一个-(减号)即可。另外ps命令可允许参数不加减号(-),因此可直接写成ps aux的样子。 top 用于动态监视进程活动与系统负载等信息。 pidof 用于查询某个指定服务进程的PID值。 举例: kill 用于终止某个指定PID的服务进程。 killall 用于终止某个指定名称的服务所对应的 全部 进程。 系统状态检测命令 ifconfig 用于获取网卡配置与网络状态等信息。 主要用处: 1使用ifconfig命令来查看本机当前的网卡配置与网络状态等信息时,其实主要查看的就是网卡名称、inet参数后面的IP地址、ether参数后面的网卡物理地址(又称为MAC地址),以及RX、TX的接收数据包与发送数据包的个数及累计流量 uname 用于查看系统内核与系统版本等信息。 1在使用uname命令时,一般会固定搭配上-a参数来完整地查看当前系统的内核名称、主机名、内核发行版本、节点名、系统时间、硬件名称、硬件平台、处理器类型以及操作系统名称等信息。 举例: 12uname -acat /etc/redhat-release uptime 用于查看系统的负载信息。 跟top第一行应该是一样的。 free 用于显示当前系统中内存的使用量信息。 举例:free -h -h人性化显示(GB,MB之类的) who 用于查看当前登入主机的用户终端信息。 last 用于查看所有系统的登录记录。 history 用于显示历史执行过的命令。 1执行history命令能显示出当前用户在本地计算机中执行过的最近1000条命令记录。如果觉得1000不够用,还可以自定义/etc/profile文件中的HISTSIZE变量值。在使用history命令时,如果使用-c参数则会清空所有的命令历史记录。还可以使用“!编码数字”的方式来重复执行某一次的命令。 sosreport 用于收集系统配置及架构信息并输出诊断文件。 1当Linux系统出现故障需要联系技术支持人员时,大多数时候都要先使用这个命令来简单收集系统的运行状态和服务配置信息,以便让技术支持人员能够远程解决一些小问题,亦或让他们能提前了解某些复杂问题。 工作目录切换命令 pwd 用于显示用户当前所处的工作目录。 cd 用于切换工作路径。 cd - 返回上一次所处的目录。 1使用“cd ..”命令进入上级目录,以及使用“cd ~”命令切换到当前用户的家目录,亦或使用“cd ~username”切换到其他用户的家目录。 ls 用于显示目录中的文件信息。 12使用ls命令的“-a”参数看到全部文件(包括隐藏文件),使用“-l”参数可以查看文件的属性、大小等详细信息。将这两个参数整合之后,再执行ls命令即可查看当前目录中的所有文件并输出这些文件的属性信息。如果想要查看目录属性信息,则需要额外添加一个-d参数。 文本文件编辑命令 Linux “一切皆文件” cat 用于查看纯文本文件(内容较少的)。 cat -n 显示行号。 more 用于查看纯文本文件。 空格或回车 翻页。 head 用于查看纯文本文档的前 N 行。 tail 用于查看纯文本文档的后 N 行或 持续刷新内容。 持续刷新内容举例 tail -f test: tr 用于替换文本文件中的字符,tr 「原始字符」 「目标字符」 wc 用于统计指定文本的行数,字数,字节数。 参数列表: wc -l /var/log/messages stat 用于查看文件的具体存储信息和时间等信息。 cut 用于按列提取文本字符。-d设置间隔符号,-f设置需要查看的列数,-c指定提取内容的字符串个数。 head -10 /etc/shadow | cut -d: -f1 head -10 /etc/passwd | cut -c2-4 diff 用于比较多个文本文件的差异。 文件目录管理命令 touch 用于创建空白文件或设置文件的时间。 1对touch命令来讲,有难度的操作主要是体现在设置文件内容的修改时间(mtime)、文件权限或属性的更改时间(ctime)与文件的读取时间(atime) 参数列表: 举例: mkdir 用于创建空白的目录。 cp 用于复制文件或目录。 参数列表: mv 用于剪切文件或将文件重命名。 rm 用于删除文件或目录。 dd 用于按照指定大小和个数的数据块来复制文件或转换文件。 参数列表: 1Linux系统中有一个名为/dev/zero的设备文件,这个文件不会占用系统存储空间,但却可以提供无穷无尽的数据,因此可以使用它作为dd命令的输入文件,来生成一个指定大小的文件。 例子: dd if=/dev/zero of=hh count=2 bs=20M 总文件大小”2*20M = 40M” file 用于查看文件的类型。 举例: 打包压缩与搜索命令 tar 用于对文件进行打包压缩或解压。 参数列表: 1234首先,-c参数用于创建压缩文件,-x参数用于解压文件,因此这两个参数不能同时使用。其次,-z参数指定使用Gzip格式来压缩或解压文件,-j参数指定使用bzip2格式来压缩或解压文件。用户使用时则是根据文件的后缀来决定应使用何种格式参数进行解压。在执行某些压缩或解压操作时,可能需要花费数个小时,如果屏幕一直没有输出,您一方面不好判断打包的进度情况,另一方面也会怀疑电脑死机了,因此非常推荐使用-v参数向用户不断显示压缩或解压的过程。-C参数用于指定要解压到哪个指定的目录。!!!(重要)-f参数特别重要,它必须放到参数的最后一位,代表要压缩或解压的软件包名称。 grep 用于在文本中执行关键词搜索,并显示匹配的结果。 参数列表: 举例: find 用于按照指定条件来查找文件。 参数列表: 例子: find / -type f -name "*.conf" -exec stat -c "%s %n" {} \; | sort -nr | head -10 12其中的{}表示搜索出的每一个文件。stat -c "%s %n" filename. 复习题12使用uptime命令查看系统负载时,对应的负载数值如果是0.91、0.56、0.32,那么最近15分钟内负载压力最大的是哪个时间段?答:通过负载数值可以看出,最近1分钟内的负载压力是最大的。]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux makefile实验]]></title>
<url>%2F2018%2F04%2F25%2FLinux%20makefile%E5%AE%9E%E9%AA%8C%2F</url>
<content type="text"><![CDATA[按照以下目录结构存放程序,然后制作makefile文件,把makefile文件内容填入表格中。 现有一个程序由5个文件组成: 123456789/* ./main.c */#include "mytool1.h"#include "mytool2.h"int main(){ mytool1_print("hello mytool1!\n"); mytool2_print("hello mytool2!\n"); return 0;} 1234567/* ./functions/mytool1.c */#include "mytool1.h"#include <stdio.h>void mytool1_print(char *print_str){ printf("This is mytool1 print : %s ",print_str);} 12345/* ./functions/mytool1.h */#ifndef _MYTOOL_1_H#define _MYTOOL_1_H void mytool1_print(char *print_str);#endif 12345678/* ./functions/mytool2.c */#include "mytool2.h"#include <stdio.h> void mytool2_print(char *print_str){ printf("This is mytool2 print : %s ",print_str);} 12345/* ./functions/mytool2.h */#ifndef _MYTOOL_2_H#define _MYTOOL_2_H void mytool2_print(char *print_str);#endif 1234567891011./Makefilemain:mytool1.o mytool2.o main.o gcc mytool1.o mytool2.o main.o -o mainmain.o:main.c ./functions/mytool1.h ./functions/mytool2.h gcc -c main.c -o main.o -I functionsmytool1.o:./functions/mytool1.c ./functions/mytool1.h gcc -c ./functions/mytool1.c -o mytool1.omytool2.o:./functions/mytool2.c ./functions/mytool2.h gcc -c ./functions/mytool2.c -o mytool2.oclean: rm -rf *.o main 输出结果:]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux shell程序设计实验2]]></title>
<url>%2F2018%2F04%2F22%2FLinux%20shell%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E5%AE%9E%E9%AA%8C2%2F</url>
<content type="text"><![CDATA[编写一个shell过程完成如下功能(必须在脚本中使用函数) 1.程序接收3个参数:$1/$2和$3,合并两个文件$1/$2为$3,并显示,三个文件均为文本文件。2.如果文件$3不存在,那么先报告缺少$3,然后将合并后的内容输出到mydoc.txt。如果有$3,就合并到$3。3.如果文件$2或文件$3不存在,那么先报告缺少$2/$3,只显示$1的内容。 4.如果文件$1不存在,则提示缺少$1,要求重新运行程序。 12345678910111213141516171819202122232425262728293031#!/bin/sh function f1(){ echo "missing \$2 and \$3" echo "output \$1:" cat $1} function f2(){ echo "missing \$3, output mydoc.txt:" cat $1 $2 >mydoc.txt cat mydoc.txt} function error(){ echo "missing \$1 \$2 \$3, error!"} if [ $# -eq 0 ]; then errorelif [ $# -eq 1 ]; then f1 $1elif [ $# -eq 2 ]; then f2 $1 $2elif [ $# -eq 3 ]; then cat $1 $2 >$3 echo "output \$3:" cat $3 fi exit 0]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux shell程序设计实验1]]></title>
<url>%2F2018%2F04%2F21%2FLinux%20shell%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E5%AE%9E%E9%AA%8C1%2F</url>
<content type="text"><![CDATA[实验1-1 设计如下一个菜单驱动程序 Use one of the following options:P:To display current directoryS:To display the name of running fileD:To display today’s date and present time (要求显示为:2017-04-26 05:45:12)L:To see the list of files in your present working directoryW:To see who is logged inQ:To quit this programEnter your option and hit:菜单程序将根据用户输入的选择项给出相应信息。要求对用户的输入忽略大小写,对于无效选项的输入给出相应提示。要求使用case语句实现以上功能,输入相应的字母后应该执行相应的命令完成每项功能,如输入P或p,就执行pwd命令。 实验1-2编写一段bash shell程序,根据键盘输入的学生成绩,显示相应的成绩登等级,其中60分以下为”Failed!”,60~69分为”Passed!”,70~79分为”Medium!”,80~89分为”Good!”,90~100为”Excellent!”。如果输入超过100的分数,则显示错误分数提示。 如果输入负数,则退出程序,否则一直提示用户输入成绩 1-1 12345678910111213141516171819202122232425262728293031323334#!/bin/bashclearecho "Use one of the following options:P:To display current directoryS:To display the name of running fileD:To display today's date and present timeL:To see the list of files in your present working directoryW:To see who is logged inQ:To quit this programEnter your option and hit:"read anscase "$ans" inP|p) pwd ;;S|s) ls ;;D|d) date -d '2017-04-26 05:45:12' '+%Y-%m-%d %H:%M:%S' ;;L|l) ls -l ;;W|w) who ;;Q|q) exit 1 ;;*) exit 1esacexit 0 1-2 12345678910111213141516171819202122232425262728#!/bin/bashwhile trueecho "Please input your score: (0 - 100)"doread scoreif [ $score -lt 0 ];then breakelif [ $score -lt 60 ];then echo "Failed!"elif [ $score -lt 70 ];then echo "Passed!"elif [ $score -lt 80 ];then echo "Medium!"elif [ $score -lt 90 ];then echo "Good!"elif [ $score -le 100 ];then echo "Excellent!"else echo "the score must be smaller than 100"fidoneexit 0]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux实验二]]></title>
<url>%2F2018%2F04%2F20%2FLinux%E5%AE%9E%E9%AA%8C%E4%BA%8C%2F</url>
<content type="text"><![CDATA[Linux实验二 实验环境:win10 + redhat51、创建组testgroup;1groupadd testgroup 2、创建用户a2012,先采用默认设置创建,然后使该用户加入testgroup组。1vi /etc/groupd //在后面添加a2012 3、创建用户a2013,其用户主目录为/tmp/a2013,其主组为testgroup,附加组为users。1useradd -d /tmp/a2013 -g testgroup -G users a2013 4、用id命令显示a2012和a2013用户信息,并且把这些信息记录到日志文件/tmp/test.log中。12su a2012id 12su 2013id 5、参考书本98-99页crontab命令内容,使用root执行crontab -e,编写时程表,完成每隔5分钟把当前时间追加进/tmp/test.log中。1crontab -e 15 * * * * data >> /tmp/test.log 6、执行crontab -l,把输出内容追加进/tmp/test.log。1crontab -l >> /tmp/test.log 7、待完成2次时间记录追加后,执行crontab -r删除当前的时程表。1crontab -r 8、把/tmp/test.log拷贝到windows中(注意文本格式的转换),采用记事本打开,看是否看到完整内容。]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux课堂练习1]]></title>
<url>%2F2018%2F04%2F16%2FLinux%E8%AF%BE%E5%A0%82%E7%BB%83%E4%B9%A01%2F</url>
<content type="text"><![CDATA[环境:win10 + redhat 5 1、创建组testgroup。1groupadd testgroup 2、创建用户a2012,先采用默认设置创建,然后使该用户加入testgroup组。12useradd a2012usermod -g testgroup 3、创建用户a2013,其用户主目录为/tmp/a2013,其主组为testgroup,附加组为users。123useradd a2013usermod -g testgroupusermod -G users 4、用id命令显示a2012和a2013用户信息,并且把这些信息记录到日志文件/tmp/test.log中。12id a2012 > /tmp/test.logid a2013 >> /tmp/test.log 5、参考书本98-99页crontab命令内容,使用root执行crontab -e,编写时程表,完成每隔5分钟把当前时间追加进/tmp/test.log中。12crontab -e*/5 * * * * date >> /tmp/test.log 6、执行crontab -l,把输出内容追加进/tmp/test.log。1crontab -l >> /tmp/test.log 7、待完成2次时间记录追加后,执行crontab -r删除当前的时程表。1crontab -r 8、把/tmp/test.log拷贝到windows中(注意文本格式的转换),采用记事本打开,看是否看到完整内容。1unix2dos test.log #将unix中的换行符转换为dos环境下能识别的类型 最后将文件复制到win环境下得到test.log]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Linux实验一]]></title>
<url>%2F2018%2F04%2F12%2FLinux%E5%AE%9E%E9%AA%8C%E4%B8%80%2F</url>
<content type="text"><![CDATA[Linux实验一 环境:win10 + redhat 51、root帐号登录,查看/tmp目录,如果/tmp目录下没有子目录myshare,则建立该目录。1ls /tmp | grep myshare 1mkdir -p /tmp/myshare 2、创建帐号testuser。1useradd testuser 1passwd testuser 3、把myshare目录及其目录下的所有文件和子目录的拥有者该为testuser,工作组改为users。1chown -R testuser:users /tmp/myshare 4、切换至testuser帐号。进入/tmp/myshare目录,采用vim编辑器编写以下程序,程序名称为hello.sh: #!/bin/bashecho “app start”echo -efunc (){ echo “hello world!”}funcecho -eecho “app end”1su testuser 1vim /tmp/myshare/hello.sh 5、保存hello.sh后,给予hello.sh拥有者可读、可写和可执行的权限,同组可读可执行,其他人可执行权限。1chmod 751 hello.sh 6、输入./hello.sh,观察程序输出的效果。1./hello.sh 7、进入testuser的用户主目录,在这个目录下创建hello.sh的软链接,同时拷贝hello.sh到该目录下并改名为hello.sh.bak,要求copy时保留文件属性值。1ln -s /tmp/myshare/hello.sh 1cp -p /tmp/myshare/hello.sh /home/testuser/hello.sh.bak 8、退出testuser帐号,回到root帐号,从/开始查找后缀名为.conf的所有文件,把输出结果重定向到testuser帐号的主目录下的output.txt文件。1exit 1find / -type f -name ".conf" >> /home/testuser/output.txt 9、在上一步操作的.conf文件中找出文件容量最大的和最小那个,并把这两个文件的容量大小输出到output.txt文件中。>>1find / -type f -name ".conf" -ls | awk '{print $7}'|sort -n > /home/testuser/tmp.out 1head -1 /home/testuser/tmp.out >> /home/testuser/output.txt 1tail -1 /home/testuser/tmp.out >> /home/testuser/output.txt 10、统计出系统中有多少个用户帐号,把数量输出到output.txt文件中。1cat /etc/passwd | wc -l >> /home/testuser/output.txt 11、把output.txt文件转换为windows记事本可正规打开的格式。1unix2doc output.txt 12、tar打包压缩testuser帐号主目录下的所有文件。1tar zcvf testuser.tar.gz /home/testuser 13、把tar文件另存在window系统下。U盘或者ftp 14、执行userdel -r testuser,执行rm -fr myshare]]></content>
<categories>
<category>Linux</category>
</categories>
<tags>
<tag>Linux实验</tag>
</tags>
</entry>
</search>