第1章 网络爬虫简介
2019-03-04 本文已影响108人
AmaAnchor
第一章 网络爬虫简介
1.1 网络爬虫何时有用
大数据时代,可以自定义要抓取的数据,并进行分析等
1.2 背景调研
1.2.1 检查robots.txt文件
在网站域名后面加上[/]robots.txt
image
1.2.2 检查网站地图
在robots.txt文件中获得sitemap文件,通常可以帮助我快速的浏览网页的所有链接
1.2.3 估算网站大小
即在域名前面加上:site 在google中进行搜索
image
1.2.4 识别网站所用技术
使用模块builtwith
In [19]: import builtwith
In [20]: builtwith.parse('http://example.python-scraping.com')
Out[20]:
{'web-servers': ['Nginx'],
'web-frameworks': ['Web2py', 'Twitter Bootstrap'],
'programming-languages': ['Python'],
'javascript-frameworks': ['jQuery', 'Modernizr', 'jQuery UI']}
1.2.5 寻找网站所有者
In [22]: print(whois.whois('appspot.com'))
1.3 编写第一个网络爬虫
1.3.1下载网页
(使用jupyter notebook)
import requests
url='http://example.python-scraping.com'
resp=requests.get(url)
(1). 重试下载
对于404 Not Found这种错误,表示网页资源不存在,而对于5xx错误码时,错误发生在服务端,此时需要重试下载。
image
(2). 设置用户代理
为什么使用用户代理?
代理代表一种身份,可以模拟不同的浏览器
image
1.3.2 ID遍历爬虫
观察示例网站下的一组网站url
http://example.python-scraping.com/places/default/view/Turkmenistan-226
http://example.python-scraping.com/places/default/view/Afghanistan-1
发现这些url只有结尾处不同,包括国家名和ID,现在将国家名移除,试探,发现url仍然可用
image
遍历ID的方法很简答,但实际用的上的地方并不多。
1.3.3 链接爬虫
使用一个链接栈,每次出栈一个url,并且获取该url下的所有满足条件的href并且拼装成url存入栈.用列表表示栈。
image
def link_crawler(start_url,retries=2,user_agent='wswp',regex='/places/default/(view|list)'):
seen=[]#已经访问过的链接不再访问
pre_url='http://example.python-scraping.com'#url前缀
if isinstance(start_url,list):
url_stack=start_url
else:
url_stack=[start_url]
while url_stack:
url=url_stack.pop()
html=download(url)
for url in re.findall(r'''<a\shref=["'](.*?)["']''',html):#匹配链接
if re.match(regex,url) and url not in seen:
url_r=pre_url+url
url_stack.append(url_r)
seen.append(url)
高级功能
解析robots.txt
In [2]: from urllib import robotparser
In [3]: rp=robotparser.RobotFileReader()
rp=robotparser.RobotFileParser()
In [5]: rp.set_url('http://example.python-scraping.com/robots.txt')
In [6]: rp.read()
In [7]: url='http://example.python-scraping.com'
In [9]: rp.can_fetch('wswo',url)
Out[9]: True
添加代理
image.png下载限速
写一个限速类:Throttle
class Throttle(object):
def __init__(self,delay):
self.delay=delay
self.domains={}#记录了每个域名上次的访问时间
def wait(self,url):
domain=urlparse(url).netloc
last_accessed=domains.get(domain)
if last_accessed and last_accessed>0:
sleep_secs=time.time()-last_accessed
if sleep_secs>0:
time.sleep(sleep_secs)
domains[domain]=time.time()
image.png
避免爬虫陷阱
一个反爬虫策略:动态生成无数多的网页,永远都爬不完,并且爬的无用的信息.
解决方案:设置最大深度——当前网页经过了多少链接
image.png
最终版本
link_crawler.py
def link_crawler(start_url,retries=2,user_agent='wswp',regex='/places/default/(view|index)',delay=2,max_depth=5):
throttle=Throttle(delay)
seen={}#已经访问过的链接不再访问 将seen由列表改为字典,并存储值当前url的深度
pre_url='http://example.python-scraping.com'#url前缀
if isinstance(start_url,list):
url_stack=start_url
else:
url_stack=[start_url]
while url_stack:
depth=seen.get('url')
if depth and depth>max_depth:
print('超过最大深度,疑为爬虫陷阱')
continue
elif depth is None:
depth=1
url=url_stack.pop()
throttle.wait(url)#下载检查是否超速下载
html=download(url)
for url in re.findall(r'''<a\shref=["'](.*?)["']''',html):#匹配链接
if re.match(regex,url) and url not in seen:
url_r=pre_url+url
url_stack.append(url_r)
seen[url]=depth+1
笔记