更新了文档

pull/6/head
jackfrued 2018-05-28 08:50:30 +08:00
parent 822ffd00d1
commit 402e056498
16 changed files with 229 additions and 28 deletions

View File

@ -342,6 +342,9 @@ Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> Dept.objects.filter(no__gt=10).filter(no__lt=40) # 查询部门编号大于10小于40的部门
<QuerySet [<Dept: 1>, <Dept: 1>]>
>>>
>>> Dept.objects.filter(no__range=(10, 30)) # 查询部门编号在10到30之间的部门
<QuerySet [<Dept: 1>, <Dept: 1>, <Dept: 1>]>
```
查询单个对象。
@ -350,8 +353,10 @@ Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> Dept.objects.get(pk=10)
<Dept: 1>
>>>
>>> Dept.objects.get(no=20)
<Dept: 1>
>>>
>>> Dept.objects.get(no__exact=30)
<Dept: 1>
```
@ -362,6 +367,7 @@ Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> Dept.objects.order_by('no') # 查询所有部门按部门编号升序排列
<QuerySet [<Dept: 1>, <Dept: 1>, <Dept: 1>, <Dept: 3>]>
>>>
>>> Dept.objects.order_by('-no') # 查询所有部门按部门编号降序排列
<QuerySet [<Dept: 3>, <Dept: 1>, <Dept: 1>, <Dept: 1>]>
```
@ -372,6 +378,7 @@ Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> Dept.objects.order_by('no')[0:2] # 按部门编号排序查询1~2部门
<QuerySet [<Dept: 1>, <Dept: 1>]>
>>>
>>> Dept.objects.order_by('no')[2:4] # 按部门编号排序查询3~4部门
<QuerySet [<Dept: 1>, <Dept: 3>]>
```
@ -382,37 +389,43 @@ Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> Emp.objects.filter(dept__no=10) # 根据部门编号查询该部门的员工
<QuerySet [<Emp: >, <Emp: >, <Emp: >]>
>>>
>>> Emp.objects.filter(dept__name__contains='销售') # 查询名字包含“销售”的部门的员工
<QuerySet [<Emp: >]>
>>>
>>> Dept.objects.get(pk=10).emp_set.all() # 通过部门反查部门所有的员工
<QuerySet [<Emp: >, <Emp: >, <Emp: >]>
```
> 说明:由于员工与部门之间存在外键关联,所以也能通过部门反向查询该部门的员工(从一对多关系中“一”的一方查询“多”的一方),默认情况下反查属性名是`类名小写_set`(例子中的`emp_set`),当然也可以在创建模型时通过`related_name`指定反查属性的名字。
> 说明1由于员工与部门之间存在多对一外键关联所以也能通过部门反向查询该部门的员工从一对多关系中“一”的一方查询“多”的一方反向查询属性默认的名字是`类名小写_set`(如上面例子中的`emp_set`),当然也可以在创建模型时通过`ForeingKey`的`related_name`属性指定反向查询属性的名字。如果不希望执行反向查询可以将`related_name`属性设置为`'+'`或以`'+'`开头的字符串。
> 说明2查询多个对象的时候返回的是QuerySet对象QuerySet使用了惰性查询即在创建QuerySet对象的过程中不涉及任何数据库活动等真正用到对象时求值QuerySet才向数据库发送SQL语句并获取对应的结果这一点在实际开发中需要引起注意
> 说明3可以在QuerySet上使用`update()`方法一次更新多个对象。
#### 删除
```Shell
>>>
>>> Dept.objects.get(pk=40).delete()
(1, {'hrs.Dept': 1})
```
最后,我们通过上面掌握的知识来实现部门展示以及根据部门获取部门对应员工信息的功能,效果如下图所示,对应的代码可以访问<>。
### Django模型最佳实践
1. 正确的模型命名和关系字段命名。
2. 设置适当的related_name属性。
3. 用OneToOneField代替ForeignKeyField(unique=True)。
4. 通过迁移操作来添加模型。
2. 设置适当的`related_name`属性。
3. 用`OneToOneField`代替`ForeignKeyField(unique=True)`
4. 通过迁移操作migrate来添加模型。
5. 用NoSQL来应对需要降低范式级别的场景。
6. 如果布尔类型可以为空要使用NullBooleanField。
6. 如果布尔类型可以为空要使用`NullBooleanField`
7. 在模型中放置业务逻辑。
8. 用ModelName.DoesNotExists取代ObjectDoesNotExists。
8. 用`<ModelName>.DoesNotExists`取代`ObjectDoesNotExists`
9. 在数据库中不要出现无效数据。
10. 不要对QuerySet调用len函数。
11. 将QuerySet的exists()方法的返回值用于if条件。
12. 用DecimalField来存储货币相关数据而不是FloatField。
13. 定义\_\_str\_\_方法。
10. 不要对`QuerySet`调用`len()`函数。
11. 将`QuerySet``exists()`方法的返回值用于`if`条件。
12. 用`DecimalField`来存储货币相关数据而不是`FloatField`
13. 定义`__str__`方法。
14. 不要将数据文件放在同一个目录中。
> 说明以上内容来自于STEELKIWI网站的[*Best Practice working with Django models in Python*](https://steelkiwi.com/blog/best-practices-working-django-models-python/),有兴趣的小伙伴可以阅读原文。
@ -513,22 +526,31 @@ ManyToManyField属性
| verbose_name | 为对象设定人类可读的名称 |
| verbose_name_plural | 设定对象的复数名称 |
### 数据库API参考
### 查询参考
按字段查找可以用的条件:
1. exact / iexact
2. contains / icontains
3. in
4. gt / gte / lt / lte
5. startswith / istartswith / endswith / iendswith
6. range
7. year / month / day / week_day / hour / minute / second
8. isnull
9. search
10. regex / iregex
1. exact / iexact精确匹配/忽略大小写的精确匹配查询
2. contains / icontains / startswith / istartswith / endswith / iendswith基于`like`的模糊查询
3. in集合运算
4. gt / gte / lt / lte大于/大于等于/小于/小于等于关系运算
5. range指定范围查询SQL中的`between…and…`
6. year / month / day / week_day / hour / minute / second查询时间日期
7. isnull查询空值True或非空值False
8. search基于全文索引的全文检索
9. regex / iregex基于正则表达式的模糊匹配查询
Q对象用于执行复杂查询的使用
```Shell
>>>
>>> from django.db.models import Q
>>> Emp.objects.filter(
... Q(name__startswith='张'),
... Q(sal__gte=5000) | Q(comm__gte=1000)
... ) # 查询名字以“张”开头 工资大于等于5000或补贴大于等于1000的员工
<QuerySet [<Emp: >]>
```
跨关系查找

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

View File

@ -0,0 +1,8 @@
## 存储数据
### 缓存和持久化
### 磁盘文件缓存
### 数据库缓存

View File

@ -0,0 +1,2 @@
## 并发下载

View File

@ -0,0 +1,2 @@
## 数据清洗

View File

@ -0,0 +1,8 @@
## 数据采集和解析
### HTML页面分析
### 三种采集方式

View File

@ -0,0 +1,159 @@
## 网络爬虫和相关工具
### 网络爬虫
网络爬虫web crawler以前经常称之为网络蜘蛛spider是按照一定的规则自动浏览万维网并获取信息的机器人程序或脚本曾经被广泛的应用于互联网搜索引擎。使用过互联网和浏览器的人都知道网页中除了供用户阅读的文字信息之外还包含一些超链接。网络爬虫系统正是通过网页中的超链接信息不断获得网络上的其它页面。正因如此网络数据采集的过程就像一个爬虫或者蜘蛛在网络上漫游所以才被形象的称为网络爬虫或者网络蜘蛛。
#### 爬虫的应用领域
在理想的状态下所有ICPInternet Content Provider都应该为自己的网站提供API接口来共享它们允许其他程序获取的数据在这种情况下爬虫就不是必需品国内比较有名的电商平台如淘宝、京东等、社交平台如腾讯微博等等网站都提供了自己的Open API但是这类Open API通常会对可以抓取的数据以及抓取数据的频率进行限制。对于大多数的公司而言及时的获取行业相关数据是企业生存的重要环节之一然而大部分企业在行业数据方面的匮乏是其与生俱来的短板合理的利用爬虫来获取数据并从中提取出有价值的信息是至关重要的。当然爬虫还有很多重要的应用领域以下列举了其中的一部分
1. 搜索引擎
2. 新闻聚合
3. 社交应用
4. 舆情监控
5. 行业数据
### 合法性和背景调研
#### 爬虫合法性探讨
1. 网络爬虫领域目前还属于拓荒阶段,虽然互联网世界已经通过自己的游戏规则建立起一定的道德规范(Robots协议全称是“网络爬虫排除标准”),但法律部分还在建立和完善中,也就是说,现在这个领域暂时还是灰色地带。
2. “法不禁止即为许可”,如果爬虫就像浏览器一样获取的是前端显示的数据(网页上的公开信息)而不是网站后台的私密敏感信息,就不太担心法律法规的约束,因为目前大数据产业链的发展速度远远超过了法律的完善程度。
3. 在爬取网站的时候需要限制自己的爬虫遵守Robots协议同时控制网络爬虫程序的抓取数据的速度在使用数据的时候必须要尊重网站的知识产权从Web 2.0时代开始虽然Web上的数据很多都是由用户提供的但是网站平台是投入了运营成本的当用户在注册和发布内容时平台通常就已经获得了对数据的所有权、使用权和分发权。如果违反了这些规定在打官司的时候败诉几率相当高。
#### Robots.txt文件
大多数网站都会定义robots.txt文件下面以淘宝的[robots.txt](http://www.taobao.com/robots.txt)文件为例,看看该网站对爬虫有哪些限制。
```
User-agent: Baiduspider
Allow: /article
Allow: /oshtml
Disallow: /product/
Disallow: /
User-Agent: Googlebot
Allow: /article
Allow: /oshtml
Allow: /product
Allow: /spu
Allow: /dianpu
Allow: /oversea
Allow: /list
Disallow: /
User-agent: Bingbot
Allow: /article
Allow: /oshtml
Allow: /product
Allow: /spu
Allow: /dianpu
Allow: /oversea
Allow: /list
Disallow: /
User-Agent: 360Spider
Allow: /article
Allow: /oshtml
Disallow: /
User-Agent: Yisouspider
Allow: /article
Allow: /oshtml
Disallow: /
User-Agent: Sogouspider
Allow: /article
Allow: /oshtml
Allow: /product
Disallow: /
User-Agent: Yahoo! Slurp
Allow: /product
Allow: /spu
Allow: /dianpu
Allow: /oversea
Allow: /list
Disallow: /
User-Agent: *
Disallow: /
```
注意上面robots.txt第一段的最后一行通过设置“Disallow: /”禁止百度爬虫访问除了“Allow”规定页面外的其他所有页面。因此当你在百度搜索“淘宝”的时候搜索结果下方会出现“由于该网站的robots.txt文件存在限制指令限制搜索引擎抓取系统无法提供该页面的内容描述”。百度作为一个搜索引擎至少在表面上遵守了淘宝网的robots.txt协议所以用户不能从百度上搜索到淘宝内部的产品信息。
![](./res/baidu-search-taobao.png)
### 相关工具介绍
#### HTTP协议
#### 相关工具
1. Chrome Developer Tools
![](./res/chrome-developer-tools.png)
2. POSTMAN
![](./res/postman.png)
3. HTTPie
```Shell
$ http --header http://www.scu.edu.cn
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, max-age=600
Connection: Keep-Alive
Content-Encoding: gzip
Content-Language: zh-CN
Content-Length: 14403
Content-Type: text/html
Date: Sun, 27 May 2018 15:38:25 GMT
ETag: "e6ec-56d3032d70a32-gzip"
Expires: Sun, 27 May 2018 15:48:25 GMT
Keep-Alive: timeout=5, max=100
Last-Modified: Sun, 27 May 2018 13:44:22 GMT
Server: VWebServer
Vary: User-Agent,Accept-Encoding
X-Frame-Options: SAMEORIGIN
```
4. BuiltWith识别网站使用的技术
```Python
>>>
>>> import builtwith
>>> builtwith.parse('http://www.bootcss.com/')
{'web-servers': ['Nginx'], 'font-scripts': ['Font Awesome'], 'javascript-frameworks': ['Lo-dash', 'Underscore.js', 'Vue.js', 'Zepto', 'jQuery'], 'web-frameworks': ['Twitter Bootstrap']}
>>>
>>> import ssl
>>> ssl._create_default_https_context = ssl._create_unverified_context
>>> builtwith.parse('https://www.jianshu.com/')
{'web-servers': ['Tengine'], 'web-frameworks': ['Twitter Bootstrap', 'Ruby on Rails'], 'programming-languages': ['Ruby']}
```
5. python-whois查询网站的所有者
```Python
>>>
>>> import whois
>>> whois.whois('baidu.com')
{'domain_name': ['BAIDU.COM', 'baidu.com'], 'registrar': 'MarkMonitor, Inc.', 'whois_server': 'whois.markmonitor.com', 'referral_url': None, 'updated_date': [datetime.datetime(2017, 7, 28, 2, 36, 28), datetime.datetime(2017, 7, 27, 19, 36, 28)], 'creation_date': [datetime.datetime(1999, 10, 11, 11, 5, 17), datetime.datetime(1999, 10, 11, 4, 5, 17)], 'expiration_date': [datetime.datetime(2026, 10, 11, 11, 5, 17), datetime.datetime(2026, 10, 11, 0, 0)], 'name_servers': ['DNS.BAIDU.COM', 'NS2.BAIDU.COM', 'NS3.BAIDU.COM', 'NS4.BAIDU.COM', 'NS7.BAIDU.COM', 'dns.baidu.com', 'ns4.baidu.com', 'ns3.baidu.com', 'ns7.baidu.com', 'ns2.baidu.com'], 'status': ['clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited', 'clientTransferProhibited https://icann.org/epp#clientTransferProhibited', 'clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited', 'serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited', 'serverTransferProhibited https://icann.org/epp#serverTransferProhibited', 'serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited', 'clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)', 'clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)', 'clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)', 'serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)', 'serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)', 'serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)'], 'emails': ['abusecomplaints@markmonitor.com', 'whoisrelay@markmonitor.com'], 'dnssec': 'unsigned', 'name': None, 'org': 'Beijing Baidu Netcom Science Technology Co., Ltd.', 'address': None, 'city': None, 'state': 'Beijing', 'zipcode': None, 'country': 'CN'}
```
6. robotparser解析robots.txt的工具
### 一个简单的爬虫
构造一个爬虫一般分为数据采集、数据处理和数据存储三个部分的内容。
首先我们要设定抓取的目标并获取网页。
1. 设置重试次数。
2. 设置用户代理。

View File

@ -249,7 +249,7 @@
### Day66~75 - [爬虫](./Day66-75)
#### Day66 - [爬虫简介和相关工具](./Day66-75/爬虫简介和相关工具.md)
#### Day66 - [网络爬虫和相关工具](./Day66-75/网络爬虫和相关工具.md)
#### Day67 - [数据采集和解析](./Day66-75/数据采集和解析.md)