Python网络爬虫学习总结
1、检查robots.txt
让爬虫了解爬取该网站时存在哪些限制。
最小化爬虫被封禁的可能,而且还能发现和网站结构相关的线索。
2、检查网站地图(robots.txt文件中发现的Sitemap文件)
帮助爬虫定位网站最新的内容,而无须爬取每一个网页。
网站地图提供了所有网页的链接,我们仍需对其谨慎处理,因为该文件经常存在缺失、过期或者不完整的问题。
3、估算网站大小
爬取效率(使用分布式)
方法:检查Google爬虫的结果(Google中搜索site:www.xxxxx.com/xxxxxx)
4、识别网站所用技术
builtwith模块
builtwith.parse(‘http://www.xxxxx.com’)
- Web2py框架、通用JavaScript:内容嵌入在HTML中,容易抓取
- AngularJS:动态加载
- ASP.NET:会话管理和表单提交
5、寻找网站所有者
WHOIS协议查询域名的注册者
python-whois包
6、下载网页
urllib2模块(urllib模块)
- urllib2.urlopen(url).read()
7、重试下载
4xx错误发生在请求存在问题时,5xx错误发生在服务端存在问题时。
5xx错误时重试下载。
num_retries 设定重试下载的次数
- urllib2.URLError as e
- e.reason
- hasattr(e, ‘code’) and 500 <= e.code <600
8、设置用户代理
因为曾经历过质量不佳的Python网络爬虫造成的服务器过载,一些网站还会封禁这个默认的用户代理(Python-urllib/2.7)
- user_agent = ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36’
- headers = {‘User-agent’: user_agent}
- urllib2.Request(url, headers=headers)
9、解析robots.txt
robotparser模块
- rp = rebotparser.RobotFileParser()
- rp.set_url(url)
- rp.read()
- rp.can_fetch(user_agent, url)
10、支持代理(翻墙)
- proxy = ’121.193.143.249:80’
- opener = urllib2.build_opener()
- proxy_params = {urlparse.urlparse(url).scheme: proxy}
- opener.add_handler(urllib2.ProxyHandler(proxy_params))
- response = opener.open(request)
11、下载限速
self.delay:延时限速
- domain = urlparse.urlparse(url).netloc # 获取domain
- last_accessed = self.domains.get(domain)
- if self.delay > 0 and last_accessed is not None:
- sleep_secs = self.delay - (datetime.now() - last_accessed).seconds
- if sleep_secs > 0:
- time.sleep(sleep_secs)
- self.domains[domain] = datetime.now()
12、避免爬虫陷阱
深度 depth
最大深度 max_depth
- max_depth = 2
- seen = {}
- depth = seen[url]
- if depth != max_depth:
- for link in links:
- if link not in seen:
- seen[link] = depth + 1
- crawl_queue.append(link)
13、链接转换为绝对链接
urlparse模块
- urlparse.urljoin(seed_url, link)
14、三种网页抓取方法
正则表达式:re.findall()
Beautiful Soup:
beautifulsoup4模块
- soup = BeautifulSoup(html, ‘html.parser’)
- soup.find()
Lxml:
lxml.html模块
- tree = lxml.html.fromstring(html)
- tree.cssselect()
15、磁盘缓存
- pickle(输入转化为字符串)
- zlib(压缩序列化字符串)
- shutil(高层次的文件操作工具)
- datetime(过期)
- urlparse(文件名urlparse.urlsplit分割URL)
16、NoSQL
- 列数据存储(HBase)
- 键值对存储(Redis)
- 面向文档的数据库(MongoDB)
- 图形数据库(Neo4j)
17、数据库缓存
- self.client = MongoClient('localhost', 27017) if client is None else client
- self.db = self.client.cache
- expires=timedelta(days=30)
- self.db.webpage.create_index('timestamp', expireAfterSeconds=expires.total_seconds())
set方法:
- from bson.binary import Binary # 二进制形式存储
- record = {'result': Binary(zlib.compress(pickle.dumps(result))), 'timestamp': datetime.utcnow()}
- self.db.webpage.update({'_id': url}, {'$set': record}, upsert=True)
get方法:
- record = self.db.webpage.find_one({'_id': url})
- pickle.loads(zlib.decompress(record['result']))
18、多线程爬虫
- threads = []
- while threads or crawl_queue:
- for thread in threads:
- if not thread.is_alive():
- threads.remove(thread)
- while len(threads) < max_threads and crawl_queue:
- thread = threading.Thread(target=process_queue)
- thread.setDaemon(True) # set daemon so main thread can exit when receives ctrl-c
- thread.start()
- threads.append(thread)
- time.sleep(SLEEP_TIME)
19、多进程爬虫
- def process_crawler(args, **kwargs):
- num_cpus = multiprocessing.cpu_count()
- #pool = multiprocessing.Pool(processes=num_cpus)
- print 'Starting {} processes'.format(num_cpus)
- processes = []
- for i in range(num_cpus):
- p = multiprocessing.Process(target=threaded_crawler, args=[args], kwargs=kwargs)
- #parsed = pool.apply_async(threaded_link_crawler, args, kwargs)
- p.start()
- processes.append(p)
- # wait for processes to complete
- for p in processes:
- p.join()
20、动态网页进行逆向工程
ajax请求数据(数据接口API)
json解析成一个字典
21、渲染动态网页
- WebKit渲染引擎(通过Qt框架可以获得该引擎的一个便捷Python接口)
- Selenium(一个用于Web应用程序测试的工具)
- PhantomJS(提供一个浏览器环境的命令行接口,你可以把它看作一个“虚拟浏览器”,除了不能浏览,其他与正常浏览器一样)
难点:需要等待AJAX请求完成之后才能加载结果,定义wait
22、表单交互
发送POST请求提交表单(重要部分cookie,cookie是网站在HTTP响应头中传输的少量数据)
- def parse_form(html):
- tree = lxml.html.fromstring(html)
- data = {}
- for e in tree.cssselect('form input'):
- if e.get('name'):
- data[e.get('name')] = e.get('value')
- return data
- data = parse_form(html)
- data['email'] = LOGIN_EMAIL
- data['password'] = LOGIN_PASSWORD
- encoded_data = urllib.urlencode(data)
- request = urllib2.Request(LOGIN_URL, encoded_data)
- response = opener.open(request)
23、使用cookie登录网站
cookie是网站在HTTP响应头中传输的少量数据,形如:Set-Cookie: session_id=example;。
浏览器将会存储这些数据,并在后续对该网站的请求头中包含它们。这样就可以让网站识别和跟踪用户。
- import cookielib
- cj = cookielib.CookieJar()
- opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
- html = opener.open(LOGIN_URL).read()
24、从浏览器加载cookie(pprint美观打印数据结构)
- import glob
- import os
- # 返回session文件路径的辅助函数
- def find_ff_sessions():
- paths = [
- '~/.mozilla/firefox/*.default', # Linux系统
- '~/Library/Application Support/Firefox/Profiles/*.default', # OS X
- '%APPDATA%/Roaming/Mozilla/Firefox/Profiles/*.default' # Windows Vista及以上版本
- ]
- for path in paths:
- filename = os.path.join(path, 'sessionstore.js')
- matches = glob.glob(os.path.expanduser(filename))
- if matches:
- return matches[0]
glob模块会返回指定路径中所有匹配的文件。
- # 把session解析到CookieJar对象的函数
- def load_ff_sessions(session_filename):
- cj = cookielib.CookieJar()
- if os.path.exists(session_filename):
- try:
- json_data = json.loads(open(session_filename, 'rb').read())
- except ValueError as e:
- print 'Error parsing session JSON:', str(e)
- else:
- for window in json_data.get('windows', []):
- for cookie in window.get('cookies', []):
- import pprint; pprint.pprint(cookie)
- c = cookielib.Cookie(0, cookie.get('name', ''), cookie.get('value', ''),
- None, False,
- cookie.get('host', ''), cookie.get('host', '').startswith('.'), cookie.get('host', '').startswith('.'),
- cookie.get('path', ''), False,
- False, str(int(time.time()) + 3600 * 24 * 7), False,
- None, None, {})
- cj.set_cookie(c)
- else:
- print 'Session filename does not exist:', session_filename
- return cj
最后我们只需要使用浏览器cookie登录:
- session_filename = find_ff_sessions()
- cj = load_ff_sessions(session_filename)
- opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
- html = opener.open(URL).read()
25、自动化表单处理(Mechanize--mechanize only works on python 2.x)
简化表单提交的高级模块Mechanize
不再需要管理cookie,而且访问表单输入框也更加容易。
- import mechanize
- br = mechanize.Browser()
- br.open(login.LOGIN_URL)
- br.select_form(nr=0)
- br['email'] = login.LOGIN_EMAIL
- br['password'] = login.LOGIN_PASSWORD
- response = br.submit()
26、验证码处理(光学字符识别(COR)运用在验证码像素基本一致、字体标准、限制在字典中的单词)
- from io import BytesIO
- import lxml.html
- from PIL import Image
- # 返回包含验证码图像的Image对象
- def extract_image(html):
- tree = lxml.html.fromstring(html)
- img_data = tree.cssselect('div#recaptcha img')[0].get('src')
- # remove data:image/png;base64, header
- img_data = img_data.partition(',')[-1]
- #open('test_.png', 'wb').write(data.decode('base64'))
- binary_img_data = img_data.decode('base64')
- file_like = BytesIO(binary_img_data)
- img = Image.open(file_like)
- #img.save('test.png')
- return img
- import pytesseract
- # 阈值化,抽取验证码中的文本
- def ocr(img):
- gray = img.convert('L')
- bw = gray.point(lambda x: 0 if x < 1 else 255, '')
- word = pytesseract.image_to_string(bw)
- ascii_word = ''.join(c for c in word if c in string.letters).lower()
- return ascii_word
27、处理复杂验证码(验证码处理API)
- 2captcha.com
- deathbycaptcha.com
- 9kw.eu(可以不需要花钱)
28、Scrapy(一个流行的网络爬虫框架,可保存结果、中断恢复爬虫)
Scrapy拥有很多简化网站抓取的高级函数
scrapy -h 查看命令的详细信息
- startproject:创建一个新项目
- genspider:根据模板生成一个新爬虫
- crawl:执行爬虫
- shell:启动交互式抓取控制台
29、Portia(一款基于Scrapy开发的开源工具)
该工具可以通过点击要抓取的网站部分来创建爬虫,这样就比手工创建CSS选择器的方式更加方便。
30、Scrapely库
使用训练数据建立从网页中抓取哪些内容的模型,并在以后抓取相同结构的其他网页时应用该模型。
- from scrapely import Scraper
- s = Scraper()
- train_url = ‘http://www.xxxxx.com/xxxxxx’
- s.train(train_url, {‘name’: ‘xxx’, ‘population’: ‘xxxx’})
- test_url = ‘xxxxxxx’
- s.scrape(test_url)
网页内容是静态的,在布局发生改变时,这种方法就会非常有用。
31、反爬虫
为什么?
- 爬虫占总PV比例较高,这样浪费钱(尤其是三月份爬虫)。
- 公司可免费查询的资源被批量抓走,丧失竞争力,这样少赚钱。
- 爬虫是否涉嫌违法? 如果是的话,是否可以起诉要求赔偿?这样可以赚钱。
怎么做?
- 后台对访问进行统计,如果单个IP或userAgent访问超过阈值,予以封锁。
- 验证码、Ajax异步加载、Noscript标签的使用、Cookie限制
Python网络爬虫学习总结的更多相关文章
- python网络爬虫学习笔记
python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...
- Python网络爬虫学习手记(1)——爬虫基础
1.爬虫基本概念 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.--------百度百科 简单的说,爬 ...
- python网络爬虫学习
网络爬虫 Requests官方中文教程地址:http://docs.python-requests.org/zh_CN/latest/user/quickstart.html Beautiful So ...
- python网络爬虫学习笔记(一)Request库
一.Requests库的基本说明 引入Rquests库的代码如下 import requests 库中支持REQUEST, GET, HEAD, POST, PUT, PATCH, DELETE共7个 ...
- python网络爬虫学习笔记(二)BeautifulSoup库
Beautiful Soup库也称为beautiful4库.bs4库,它可用于解析HTML/XML,并将所有文件.字符串转换为'utf-8'编码.HTML/XML文档是与“标签树一一对应的.具体地说, ...
- 第3次作业-MOOC学习笔记:Python网络爬虫与信息提取
1.注册中国大学MOOC 2.选择北京理工大学嵩天老师的<Python网络爬虫与信息提取>MOOC课程 3.学习完成第0周至第4周的课程内容,并完成各周作业 4.提供图片或网站显示的学习进 ...
- 第三次作业-MOOC学习笔记:Python网络爬虫与信息提取
1.注册中国大学MOOC 2.选择北京理工大学嵩天老师的<Python网络爬虫与信息提取>MOOC课程 3.学习完成第0周至第4周的课程内容,并完成各周作业 第一周 Requests库的爬 ...
- 学习推荐《精通Python网络爬虫:核心技术、框架与项目实战》中文PDF+源代码
随着大数据时代的到来,我们经常需要在海量数据的互联网环境中搜集一些特定的数据并对其进行分析,我们可以使用网络爬虫对这些特定的数据进行爬取,并对一些无关的数据进行过滤,将目标数据筛选出来.对特定的数据进 ...
- 假期学习【六】Python网络爬虫2020.2.4
今天通过Python网络爬虫视频复习了一下以前初学的网络爬虫,了解了网络爬虫的相关规范. 案例:京东的Robots协议 https://www.jd.com/robots.txt 说明可以爬虫的范围 ...
随机推荐
- websocke前世今生
注:以下内容来自网上.本人经过加工整理. 1.问什么要用websocke? Browser已经支持http协议,为什么还要开发一种新的WebSocket协议呢?我们知道http协议是一种单向的网络协议 ...
- 使用Ultra Librarian转换芯片的Altium Designer封装格式
第一步:找到对应芯片的CAD文件,以OPA350为例: http://www.ti.com/product/opa350 RE: 使用Ultra Librarian转换TI芯片的Altium De ...
- 修改php上传文件尺寸、响应时间、时区时间等设置
修改php上传文件尺寸.响应时间 1.修改php.ini 1.post_max_size 指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值,默认为8M(改为150M),看你自己需要进行 ...
- Sqrt算法
转自原文:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 一个Sqrt函数引发的血案 2010-10 ...
- ZOJ 3436 July Number(DFS)
题意 把一个数替换为这个数相邻数字差组成的数 知道这个数仅仅剩一位数 若最后的一位数是7 则称原来的数为 July Number 给你一个区间 求这个区间中July Number的个数 ...
- c++ const enum #define
最后的最后,我们略微总结一下: 1.只是声明单一固定值,尽可能采用const. 2.如果是一组固定值,并且互相有关联,则采用enum. 3.不涉及条件编译,只 ...
- Linux 权限修改
chown -R 用户名:组名 文件夹名chown -R xu:hadoop hadoop 将hadoop目录(以及其下的所有子目录/文件)的属主用户设为xu, xu 的组名为group
- Win7配置SVN详细步骤(服务器和客户端)
下载并安装服务器端SVN VisualSVN Server 下载并安装客户端SVN TortoiseSVN 创建SVN库 在C盘创建文件夹MySVN(可自由命名),打开文件夹----右键Torto ...
- JavaScript 中的执行上下文和调用栈是什么?
http://zcfy.cc/article/what-is-the-execution-context-amp-stack-in-javascript-by-david-shariff-4007.h ...
- 第一章 Spring.Net介绍
1.1 概述 在Java社区中Spring经历的长时间的考验,已经是一套很成熟稳定的框架.而Spring.Net 的前身是 Java版的Spring.Spring.Net是以Java版的Spring框 ...