|
@@ -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响应(响应行+响应头+空行+消息体):
|
|
|
|
|
|
|
|
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响应(响应行+响应头+空行+消息体):
|
|
|
|
|
|
|
|
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响应(响应行+响应头+空行+消息体):
|
|
|
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
|
|
|
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',)):
|
|
|
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',)):
|
|
|
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):
|
|
|
|
|
|
|
|
|
|
|
|
|
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():
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
if __name__ == '__main__':
|
|
|
main()
|
|
main()
|
|
|
-
|
|
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-由于使用了MySQL实现持久化操作,所以要先启动MySQL服务器再运行该程序。
|
|
|
|
|
|
|
+由于使用了MySQL实现持久化操作,所以要先启动MySQL服务器并创建名为`crawler`的数据库和名为`tb_result`的二维表才能运行该程序。
|
|
|
|
|
|
|
|
### 爬虫注意事项
|
|
### 爬虫注意事项
|
|
|
|
|
|
|
@@ -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__':
|
|
|
web_page = urllib.request.urlopen(request, context=context)
|
|
web_page = urllib.request.urlopen(request, context=context)
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
- - 设置全局的取消证书验证
|
|
|
|
|
|
|
+ - 设置全局性取消证书验证
|
|
|
|
|
|
|
|
```Python
|
|
```Python
|
|
|
import ssl
|
|
import ssl
|