Commit d9ec8119 authored by jackfrued's avatar jackfrued

更新了部分文档和QQ群信息

parent 0a4d03f9
...@@ -115,7 +115,11 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -115,7 +115,11 @@ HTTP响应(响应行+响应头+空行+消息体):
3. HTTPie:命令行HTTP客户端。 3. HTTPie:命令行HTTP客户端。
```Shell ```Shell
$ http --header http://www.scu.edu.cn pip3 install httpie
```
```Shell
http --header http://www.scu.edu.cn
HTTP/1.1 200 OK HTTP/1.1 200 OK
Accept-Ranges: bytes Accept-Ranges: bytes
Cache-Control: private, max-age=600 Cache-Control: private, max-age=600
...@@ -136,6 +140,10 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -136,6 +140,10 @@ HTTP响应(响应行+响应头+空行+消息体):
4. BuiltWith:识别网站所用技术的工具。 4. BuiltWith:识别网站所用技术的工具。
```Shell
pip3 install builtwith
```
```Python ```Python
>>> import builtwith >>> import builtwith
>>> builtwith.parse('http://www.bootcss.com/') >>> builtwith.parse('http://www.bootcss.com/')
...@@ -149,6 +157,10 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -149,6 +157,10 @@ HTTP响应(响应行+响应头+空行+消息体):
5. python-whois:查询网站所有者的工具。 5. python-whois:查询网站所有者的工具。
```Shell
pip3 install python-whois
```
```Python ```Python
>>> import whois >>> import whois
>>> whois.whois('baidu.com') >>> whois.whois('baidu.com')
...@@ -158,13 +170,10 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -158,13 +170,10 @@ HTTP响应(响应行+响应头+空行+消息体):
6. robotparser:解析robots.txt的工具。 6. robotparser:解析robots.txt的工具。
```Python ```Python
>>> from urllib import robotparser >>> from urllib import robotparser
>>> parser = robotparser.RobotFileParser() >>> parser = robotparser.RobotFileParser()
>>> parser.set_url('https://www.taobao.com/robots.txt') >>> parser.set_url('https://www.taobao.com/robots.txt')
>>> parser.read() >>> parser.read()
>>> parser.can_fetch('Hellokitty', 'http://www.taobao.com/article')
False
>>> parser.can_fetch('Baiduspider', 'http://www.taobao.com/article') >>> parser.can_fetch('Baiduspider', 'http://www.taobao.com/article')
True True
>>> parser.can_fetch('Baiduspider', 'http://www.taobao.com/product') >>> parser.can_fetch('Baiduspider', 'http://www.taobao.com/product')
...@@ -200,8 +209,8 @@ import ssl ...@@ -200,8 +209,8 @@ import ssl
from pymysql import Error from pymysql import Error
# 通过指定的字符集对页面进行解码(不是每个网站都将字符集设置为utf-8)
def decode_page(page_bytes, charsets=('utf-8',)): def decode_page(page_bytes, charsets=('utf-8',)):
"""通过指定的字符集对页面进行解码(不是每个网站都将字符集设置为utf-8)"""
page_html = None page_html = None
for charset in charsets: for charset in charsets:
try: try:
...@@ -213,8 +222,8 @@ def decode_page(page_bytes, charsets=('utf-8',)): ...@@ -213,8 +222,8 @@ def decode_page(page_bytes, charsets=('utf-8',)):
return page_html return page_html
# 获取页面的HTML代码(通过递归实现指定次数的重试操作)
def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)): def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)):
"""获取页面的HTML代码(通过递归实现指定次数的重试操作)"""
page_html = None page_html = None
try: try:
page_html = decode_page(urlopen(seed_url).read(), charsets) page_html = decode_page(urlopen(seed_url).read(), charsets)
...@@ -226,14 +235,14 @@ def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)): ...@@ -226,14 +235,14 @@ def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)):
return page_html return page_html
# 从页面中提取需要的部分(通常是链接也可以通过正则表达式进行指定)
def get_matched_parts(page_html, pattern_str, pattern_ignore_case=re.I): def get_matched_parts(page_html, pattern_str, pattern_ignore_case=re.I):
"""从页面中提取需要的部分(通常是链接也可以通过正则表达式进行指定)"""
pattern_regex = re.compile(pattern_str, pattern_ignore_case) pattern_regex = re.compile(pattern_str, pattern_ignore_case)
return pattern_regex.findall(page_html) if page_html else [] return pattern_regex.findall(page_html) if page_html else []
# 开始执行爬虫程序并对指定的数据进行持久化操作
def start_crawl(seed_url, match_pattern, *, max_depth=-1): def start_crawl(seed_url, match_pattern, *, max_depth=-1):
"""开始执行爬虫程序并对指定的数据进行持久化操作"""
conn = pymysql.connect(host='localhost', port=3306, conn = pymysql.connect(host='localhost', port=3306,
database='crawler', user='root', database='crawler', user='root',
password='123456', charset='utf8') password='123456', charset='utf8')
...@@ -268,6 +277,7 @@ def start_crawl(seed_url, match_pattern, *, max_depth=-1): ...@@ -268,6 +277,7 @@ def start_crawl(seed_url, match_pattern, *, max_depth=-1):
def main(): def main():
"""主函数"""
ssl._create_default_https_context = ssl._create_unverified_context ssl._create_default_https_context = ssl._create_unverified_context
start_crawl('http://sports.sohu.com/nba_a.shtml', start_crawl('http://sports.sohu.com/nba_a.shtml',
r'<a[^>]+test=a\s[^>]*href=["\'](.*?)["\']', r'<a[^>]+test=a\s[^>]*href=["\'](.*?)["\']',
...@@ -276,10 +286,9 @@ def main(): ...@@ -276,10 +286,9 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
由于使用了MySQL实现持久化操作,所以要先启动MySQL服务器运行该程序。 由于使用了MySQL实现持久化操作,所以要先启动MySQL服务器并创建名为`crawler`的数据库和名为`tb_result`的二维表才能运行该程序。
### 爬虫注意事项 ### 爬虫注意事项
...@@ -287,7 +296,7 @@ if __name__ == '__main__': ...@@ -287,7 +296,7 @@ if __name__ == '__main__':
1. 处理相对链接。有的时候我们从页面中获取的链接不是一个完整的绝对链接而是一个相对链接,这种情况下需要将其与URL前缀进行拼接(`urllib.parse`中的`urljoin()`函数可以完成此项操作)。 1. 处理相对链接。有的时候我们从页面中获取的链接不是一个完整的绝对链接而是一个相对链接,这种情况下需要将其与URL前缀进行拼接(`urllib.parse`中的`urljoin()`函数可以完成此项操作)。
2. 设置代理服务。有些网站会限制访问的区域(例如美国的Netflix屏蔽了很多国家的访问),有些爬虫需要隐藏自己的身份,在这种情况下可以设置使用代理服务器,代理服务器有免费(如[西刺代理](http://www.xicidaili.com/)、[快代理](https://www.kuaidaili.com/free/))和付费两种(如[讯代理](http://www.xdaili.cn/)、[阿布云代理](https://www.abuyun.com/)),付费的一般稳定性和可用性都更好,可以通过`urllib.request`中的`ProxyHandler`来为请求设置代理 2. 设置代理服务。有些网站会限制访问的区域(例如美国的Netflix屏蔽了很多国家的访问),有些爬虫需要隐藏自己的身份,在这种情况下可以设置使用代理服务器,代理服务器有免费的服务器和付费的商业服务器,但后者稳定性和可用性都更好,强烈建议在商业项目中使用付费的代理服务器。可以通过修改`urllib.request`中的`ProxyHandler`来为请求设置代理服务器
3. 限制下载速度。如果我们的爬虫获取网页的速度过快,可能就会面临被封禁或者产生“损害动产”的风险(这个可能会导致吃官司且败诉),可以在两次下载之间添加延时从而对爬虫进行限速。 3. 限制下载速度。如果我们的爬虫获取网页的速度过快,可能就会面临被封禁或者产生“损害动产”的风险(这个可能会导致吃官司且败诉),可以在两次下载之间添加延时从而对爬虫进行限速。
...@@ -305,7 +314,7 @@ if __name__ == '__main__': ...@@ -305,7 +314,7 @@ if __name__ == '__main__':
web_page = urllib.request.urlopen(request, context=context) web_page = urllib.request.urlopen(request, context=context)
``` ```
- 设置全局取消证书验证 - 设置全局取消证书验证
```Python ```Python
import ssl import ssl
......
This diff is collapsed.
...@@ -302,76 +302,3 @@ Scrapy的整个数据处理流程由Scrapy引擎进行控制,通常的运转 ...@@ -302,76 +302,3 @@ Scrapy的整个数据处理流程由Scrapy引擎进行控制,通常的运转
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
``` ```
### 补充说明
#### XPath语法
1. XPath路径表达式:XPath使用路径表达式来选取XML文档中的节点或者节点集。
2. XPath节点:元素、属性、文本、命名空间、处理指令、注释、根节点。
3. XPath语法。(注:下面的例子来自于[菜鸟教程](http://www.runoob.com/)网站的[XPath教程](http://www.runoob.com/xpath/xpath-syntax.html)。)
XML文件。
```XML
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
```
XPath语法。
| 路径表达式 | 结果 |
| --------------- | ------------------------------------------------------------ |
| bookstore | 选取 bookstore 元素的所有子节点。 |
| /bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
| bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
| //book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
| bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
| //@lang | 选取名为 lang 的所有属性。 |
XPath谓词。
| 路径表达式 | 结果 |
| ---------------------------------- | ------------------------------------------------------------ |
| /bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
| /bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
| /bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
| /bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
| //title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
| //title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
| /bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
| /bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
通配符用法。
| 路径表达式 | 结果 |
| ------------ | --------------------------------- |
| /bookstore/* | 选取 bookstore 元素的所有子元素。 |
| //* | 选取文档中的所有元素。 |
| //title[@*] | 选取所有带有属性的 title 元素。 |
选取多个路径。
| 路径表达式 | 结果 |
| -------------------------------- | ------------------------------------------------------------ |
| //book/title \| //book/price | 选取 book 元素的所有 title 和 price 元素。 |
| //title \| //price | 选取文档中的所有 title 和 price 元素。 |
| /bookstore/book/title \| //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
#### 在Chrome浏览器中查看元素XPath语法
![](./res/douban-xpath.png)
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
> 作者:骆昊 > 作者:骆昊
> >
> 最近有很多想学习Python的小伙伴申请单独加我微信和QQ,因为我自己平时也很忙,没办法一一解答大家的问题,我创建了**Python100天学习交流7群**(之前的6个群已经基本满员),群号为**784430256**,二维码在下方。我的同事和朋友也在这个群里,他们很多都是优秀的Python开发者,有丰富的商业项目经验,我们在闲暇的时候会为大家解答问题,内容包括但不限于Python语言基础、Web后端开发、网络数据采集、数据分析和机器学习。我们希望这个群能够慢慢汇集资深人士和行业大咖,营造一个相对纯粹的技术社区。以后我们争取每周做一次视频直播,以专题的形式分享Python开发的点点滴滴,同时还会不定期的举办线上和线下的技术交流和分享活动,小伙伴们可以加群进行交流。创作不易,感谢各位小伙伴的打赏支持,这些钱不会用于购买咖啡而是捐赠给支教组织([点击](./更新日志.md)了解捐赠情况)。感谢**北京千锋互联科技有限公司Python教学部**对[公开课](https://ke.qq.com/course/406954)的支持。 > 最近有很多想学习Python的小伙伴单独加我微信和QQ,因为我自己平时也很忙,没办法一一解答大家的问题,我创建了**Python100天学习交流8群**(之前创建的几个交流群已经全部满员),新的交流群群号为**789050736**,二维码在下方。群里有优秀的Python开发者和行业大咖,也有刚刚开始接触Python的小白,我们希望借助这个项目,为大家提供一个沟通和交流的平台,我自己也会在闲暇的时候为大家解答问题,交流的内容包括但不限于Python语言基础、Web后端开发、网络数据采集、数据分析和机器学习。我们希望营造一个相对纯粹的技术社区,争取每周做一次专题视频直播,不定期的举办线上和线下的技术交流和分享活动,对Python感兴趣的小伙伴们可以加群进行交流。创作不易,感谢大家的打赏支持,这些钱不会用于购买咖啡而是捐赠给支教组织([点击](./更新日志.md)了解捐赠情况)。感谢**北京千锋互联科技有限公司Python教学部**对[公开课](https://ke.qq.com/course/406954)提供的支持。
![](./res/qq_group.png) ![](./res/python_qq_group.png)
> **温馨提示**:Python100天学习交流**6群已满**,请加入新群! > **温馨提示**:Python100天学习交流7群已满员,请加入新的交流群。
### Python应用领域和就业形势分析 ### Python应用领域和就业形势分析
......
## 使用Hexo搭建自己的博客
对于一个程序员来说,搭建一个属于自己的博客平台是非常有意义的事情。首先,博客可以记录自己的成长历程,也是对自己一段时间学习和工作的总结和沉淀;其他,通过博客可以营销自己,增强自己在互联网或行业内的影响力,为将来更好的职业生涯打一个坚实的基础。前几年有一本名为《软技能 - 代码之外的生存指南》的畅销书,我记得书中有这么一段话:“流行乐队的音乐才华可能并不比夜店驻场乐队高多少,他们为什么就可以在全世界巡回演出,创造一个又一个白金记录?……你的营销做得越好,你的才华才能表现得淋漓尽致。”
这里顺便啰嗦两句,在互联网如此发达的今天,我们应该如何营销自己呢?自我营销首先要从打造个人品牌做起,对于程序员来说,最容易去做好的一件事情还是搭建自己的博客。博客相当于是你在互联网上的一个基地,尤其是当你拥有了属于自己的独立博客后,你可以做很多自己想做的事情,既可以传达自己的思想,又可以提升自己的影响力,当然如果你的博客经营得非常好,你可以从中获利。当然,除了博客,直播、视频网站、投稿、写书、技术活动都是可选的自我营销方式。当然,做自我营销也需要持之以恒,三天打鱼两天晒网是很难有什么收获的。
### Hexo概述
Hexo是一个快速、简洁且高效的博客框架,它能够将[Markdown格式](<https://zh.wikipedia.org/zh-hans/Markdown>)的文档渲染成漂亮的网页,这样我们就可以在很短的时间内迅速的创建出网站的静态内容,而Markdown格式对程序员来说相信并不陌生。要想使用Hexo来搭建自己的博客,我实在想不出有什么教程比[官方文档](<https://hexo.io/zh-cn/>)更好,强烈建议大家阅读官方文档来了解Hexo,下面我只做一个简要的使用说明。
> 说明:**Markdown**是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,同时也对图片、图表、数学公式提供了支持,可以用来书写电子书、软件文档等,同时也可以非常方便的转换为HTML页面或者是PDF文档。
要使用Hexo,首先得确保计算机上已经安装了[node.js](<https://nodejs.org/en/>)环境和[git](<https://git-scm.com/>)环境,前者是一个能够在服务器端运行JavaScript代码的环境,后者是版本控制工具。如果没有安装node.js和git的经验,建议参考官方文档上的讲解,安装完成后,我们可以通过下面的命令来确认node.js环境以及它的包管理工具是否安装成功。
```Shell
node --version
npm --version
```
可以通过下面的命令来检查是否安装了git环境。
```Shell
git --version
```
我们可以使用npm来安装Hexo,npm是node.js的包管理工具,跟Python的pip工具作用一样,可以用它来安装依赖库和三方工具。在第一次使用npm的时候,我们可以先将npm的下载源更换为国内的淘宝镜像,这样下载的速度会有非常显著的提升。
```Shell
npm config set registry https://registry.npm.taobao.org
```
接下来我们就通过npm来安装Hexo,命令如下所示。
```Shell
npm install -g hexo-cli
```
安装成功后,就可以使用Hexo来创建一个博客文件夹。
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment