做婚纱影楼网站的价格,电子商务系统的组成,wordpress花园,快速做彩平图得网站1. Fiddler 设置 这是使用 fiddler 进行手机 app 的抓包#xff0c;也可以使用 Charles#xff0c;burpSuite 等。。。 
电脑安装 Fiddler#xff0c;手机 和 安装 fiddler 的电脑处于同一个网络里#xff0c; 否则手机不能把 HTTP 发送到 Fiddler 的机器上来。配置 Fiddle…  1. Fiddler 设置 这是使用 fiddler 进行手机 app 的抓包也可以使用 CharlesburpSuite 等。。。 
电脑安装 Fiddler手机 和 安装 fiddler 的电脑处于同一个网络里 否则手机不能把 HTTP 发送到 Fiddler 的机器上来。配置 Fiddler允许远程连接。用 Fiddler 对 Android 应用进行抓包 
启动Fiddler打开菜单栏中的 Tools  Fiddler Options打开“Fiddler Options”对话框。 在Fiddler Options”对话框切换到“Connections”选项卡然后勾选“Allow romote computers to connect”后面的复选框然后点击“OK”按钮。 在本机命令行输入ipconfig找到本机的 ip 地址。 2. 移动设备设置 2.1. 安卓手机设置 
Android 设备上的代理服务器设置“” 
打开 android 设备的 “设置”-“WLAN”找到你要连接的网络在上面长按然后选择“修改网络”弹出网络设置对话框在接下来弹出的对话框中勾选“显示高级选项”。在接下来显示的页面中点击“代理”选择“手动”。然后在“代理服务器主机名”后面的输入框输入电脑的ip地址在“代理服务器端口”后面的输入框输入8888然后点击“保存”按钮。
代理服务器主机名设为 PC 的 IP代理服务器端口设为Fiddler上配置的端口8888点保存。 然后启动 android 设备中的浏览器访问百度的首页在 fiddler 中可以看到完成的请求和响应数据。 2.2. IOS 应用进行抓包 
打开 IPhone 找到网络连接 打开 HTTP 代理 输入 Fiddler 所在机器的 IP 地址(比如:192.168.1.104) 以及 Fiddler 的端口号8888 2.3 安装证书、捕获 HTTPS  
只能捕获 HTTP而不能捕获 HTTPS 的解决办法 
为了让 Fiddler 能捕获 HTTPS 请求需要在 安卓设备 或者 苹果设备上安装 证书
IOS 设备步骤 
首先要知道 Fiddler 所在的机器的 IP 地址假如我安装了 Fiddle r的机器的IP地址是:192.168.1.104打开IPhone 的Safari, 访问 http://192.168.0.52:8888 点FiddlerRoot certificate 然后安装证书过证书校验 
上面的设置还不能抓像招商银行、支付宝等 APP的 https 包因为这些 APP 对 https 证书进行了校验还需要将 Fiddler 代理服务器的证书导到 Android 设备上才能抓这些 APP 的包 
导入的过程: 
打开浏览器在地址栏中输入代理服务器的IP和端口会看到一个Fiddler提供的页面 点击页面中的 “FiddlerRootcertificate” 链接接着系统会弹出对话框 输入一个证书名称然后直接点“确定”就好了。 
注意用完了 记得把 IPhone 上的 Fiddle r代理关闭 以免 IPhone 上不了网。 也可以使用模拟器例如雷电、夜神、蓝叠  等等。。 3. 斗鱼app、妹子图app 斗鱼 官网https://www.douyu.com/    斗鱼 app 下载https://www.douyu.com/client?tabclient#mobile 
可以到 妹子图官网 下载 妹子图app 
创建项目 douyu 
scrapy startproject douyu 
树形图展示项目 
cd douyu/
tree Sublime 打开项目 
subl . 生成采集模块 spider 
使用 genspider 在当前项目中创建 spider。语法: scrapy genspider [-t template] name domain 
$ scrapy genspider -l
Available templates:basiccrawlcsvfeedxmlfeed$ scrapy genspider -d basic
import scrapyclass $classname(scrapy.Spider):name  $nameallowed_domains  [$domain]start_urls  (http://www.$domain/,)def parse(self, response):pass$ scrapy genspider -t basic example example.com
Created spider example using template basic in module:mybot.spiders.example 
创建 
scrapy genspider douyu_spider douyucdn.cn编辑项目 
item.py 
import scrapyclass DouyuItem(scrapy.Item):# define the fields for your item here like:data  scrapy.Field()image_path  scrapy.Field()pass setting.py 
设置 USER_AGENT 
USER_AGENT  DYZB/2.271 (iPhone; iOS 9.3.2; Scale/3.00) douyu_spider.py  
# -*- coding: utf-8 -*-import json
import scrapyclass DouYuSpider(scrapy.spiders.Spider):name  douyu_spiderallowed_domains  [douyucdn.cn]添加内容offset  0start_urls  [fhttp://capi.douyucdn.cn/api/v1/getVerticalRoom?limit20offset{offset}]def parse(self, response):添加内容data  json.loads(response.body)[data]if not data:returnfor it in data:# item  DouyuItem()item  dict()item[image_url]  it[vertical_src]item[data]  it# yield itemprint(item)self.offset  20yield scrapy.Request(fhttp://capi.douyucdn.cn/api/v1/getVerticalRoom?limit20offset{self.offset},callbackself.parse)if __name__  __main__:from scrapy import cmdlinecmdline.execute(scrapy crawl douyu_spider.split())pass pipeline.py 
文件系统存储: 文件以它们URL的 SHA1 hash 作为文件名 
sha1sum sha1sum对文件进行唯一较验的hash算法  
用法: sha1sum [OPTION] [FILE]... 参数 -b, --binary 二进制模式读取 -c, --check 根据sha1 num检查文件 -t, --text 文本模式读取默认 
举例 
f51be4189cce876f3b1bbc1afb38cbd2af62d46b  scrapy.cfg 
{ image_path: full/9fdfb243d22ad5e85b51e295fa60e97e6f2159b2.jpg, image_url: uhttp://staticlive.douyucdn.cn/upload/appCovers/845876/20160816/c4eea823766e2e5e018eee6563e4c420_big.jpg } 
测试 
sudo vi test.txt
拷贝内容
http://staticlive.douyucdn.cn/upload/appCovers/845876/20160816/c4eea823766e2e5e018eee6563e4c420_big.jpg
sha1sum test.txt 
9fdfb243d22ad5e85b51e295fa60e97e6f2159b2 test.txt参考文档http://doc.scrapy.org/en/latest/topics/media-pipeline.html 
下面是你可以在定制的图片管道里重写的方法 
class scrapy.pipelines.images.ImagesPipeline  ( ImagesPipeline 是 FilesPipeline 的扩展 ) 
get_media_requests(item, info) 管道会得到文件的 URL 并从项目中下载。需要重写 get_media_requests() 方法 并对各个图片 URL 返回一个 Request。 Must return a Request for each image URL.  def get_media_requests(self, item, info):for image_url in item[image_urls]:yield scrapy.Request(image_url) 
item_completed(results, item, info)
当它们完成下载后结果将以2-元素的元组列表形式传送到item_completed() 方法 results 参数: 每个元组包含 (success, file_info_or_error): success 是一个布尔值当图片成功下载时为 True因为某个原因下载失败为False  file_info_or_error 是一个包含下列关键字的字典如果成功为 True或者出问题时为Twisted Failure url - 文件下载的url。这是从 get_media_requests() 方法返回请求的url。path - 图片存储的路径checksum - 图片内容的 MD5 hash下面是 item_completed(results, items, info)中 results 参数的一个典型值: 
[(True,
{checksum: 2b00042f7481c7b056c4b410d28f33cf,path: full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg,url: http://staticlive.douyucdn.cn/upload/appCovers/420134/20160807/f18f869128d038407742a7c533070daf_big.jpg}),
(False,
Failure(...))] 
默认 get_media_requests() 方法返回 None 这意味着项目中没有文件可下载。 
item_completed(results, items, info) 
当图片请求完成时要么完成下载要么因为某种原因下载失败,该方法将被调用 item_completed() 方法需要返回一个输出其将被送到随后的项目管道阶段因此你需要返回或者丢弃项目 举例 其中我们将下载的图片路径传入到results中存储到file_paths 项目组中如果其中没有图片我们将丢弃项目: 
from scrapy.exceptions import DropItemdef item_completed(self, results, item, info):image_paths   [x[path] for ok, x in results if ok]image_pathss[]for ok, x in results:if ok:image_paths.append(x[path])return image_pathsif not image_paths :raise DropItem(Item contains no images)item[image_paths]  image_pathsreturn item 
默认情况下item_completed()方法返回项目 定制图片管道: 
下面是项目图片管道 
import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItemclass ImagesPipeline(ImagesPipeline):def get_media_requests(self, item, info):image_url  item[image_url]yield scrapy.Request(image_url)def item_completed(self, results, item, info):image_paths  [x[path] for ok, x in results if ok]if not image_paths:raise DropItem(Item contains no images)item[image_path]  image_paths[0]return item 
启用pipelines 
设置图片下载位置 
是定义在 IMAGES_STORE 设置里的文件夹 
IMAGES_STORE  /home/python/project/douyu/photos 
启用PIPELINES设置item后处理模块 
ITEM_PIPELINES  {
douyu.pipelines.ImagesPipeline: 300,
} 
运行爬虫 
scrapy runspider douyu/spiders/douyu_spider.py
或者是 scrapy crawl douyu_spider 
项目还缺什么 item 存储、pipeline.py 编写 
import json
import codecsclass JsonWriterPipeline(object):def __init__(self):self.file  codecs.open(items.json, w, encodingutf-8)def process_item(self, item, spider):line  json.dumps(dict(item), ensure_asciiFalse)  \nself.file.write(line)return itemdef spider_closed(self, spider):self.file.close() 
启用 JsonWriterPipeline 编写 
ITEM_PIPELINES  {douyu.pipelines.ImagesPipeline: 300,douyu.pipelines.JsonWriterPipeline: 800,
} 
再次运行 scrapy crawl douyu_spider 美团 App 热门商圈团购采集 (1) 环境针对美团版本5.4 在 tutorial 项目下新建一个 spider 
scrapy genspider -t basic Meituan_City meituan.com 
编辑items.py 
class MeituanCity(Item):
data  Field() 
编辑 Meituan_City.py 
# -*- coding: utf-8 -*-
import scrapy
import json
from tutorial.items import MeituanCityclass MeituanCitySpider(scrapy.Spider):name  Meituan_Cityallowed_domains  [meituan.com]start_urls  (http://api.mobile.meituan.com/group/v1/city/list?showall,)def parse(self, response):data  json.loads(response.body)for item in data[data]:cityId  item[id]# http://api.mobile.meituan.com/group/v2/area/list?cityId42spatialFieldscenterurl  http://api.meituan.com/group/v2/area/list?cityId%sspatialFieldscenter % cityIdprint urlyield scrapy.Request(url,callbackself.Parse_Geo,meta{item: item})breakdef Parse_Geo(self, response):print response.urldata  json.loads(response.body)metaitem  response.meta[item]# 商区信息subareasinfo  dict()if data in data:if subareasinfo in data[data]:for item in data[data][subareasinfo]:subareasinfo[item[id]]  itemif data in data:if areasinfo in data[data]:for line in data[data][areasinfo]:# 行政区districtName  line[name]districtId  line[id]for tmp in line[subareas]:# 商圈信息area  subareasinfo[tmp]center  area[center]center  center.replace(POINT(, ).replace(), ).split()if len(center)  1:lat  center[1]lng  center[0]longitude  Nonelatitude  Nonetry:longitude  str(int(float(lng) * 1000000))latitude  str(int(float(lat) * 1000000))except:passItem  MeituanCity()Item[data] dict()geoItemItem[data] # 城市信息geoItem[cityid]  metaitem[id]geoItem[cityname]  metaitem[name]# 行政区geoItem[districtId]  districtIdgeoItem[districtName]  districtName# 商圈geoItem[SubAreaId]  area[id]geoItem[secondArea]  area[name]# 经纬度geoItem[longitude]  longitudegeoItem[latitude]  latitudeyield Item 
此时运行 
scrapy runspider tutorial/spiders/Meituan_City.py 美团 App 热门商圈团购采集 (2) 把上节内容生成的城市信息 items.json改成city_items.json 作为第二部分爬虫的启动数据 
添加items.py 
class MeituanItem(Item):data  Field() 
创建模板 
scrapy genspider -t basic Meituan_meishi meituan.com 
添加以下代码到Meituan_meishi.py 
# -*- coding: utf-8 -*-
import scrapy
import codecs
import json
from tutorial.items import MeituanItem
import reclass MeituanMeishiSpider(scrapy.Spider):美食团购页面信息采集name  Meituan_meishiallowed_domains  [meituan.com]start_urls  (http://www.meituan.com/,)offset  0def start_requests(self):file  codecs.open(city_items.json, r, encodingutf-8)for line in file:item  json.loads(line)cityid  item[data][cityid]latitude  item[data][latitude]longitude item[data][longitude]lat  round(float(latitude), 6)lng round(float(longitude), 6)url  http://api.mobile.meituan.com/group/v4/deal/select/city/42/cate/1?sortdefaultsmypos str(lat) %2C str(lng) offset0limit15yield scrapy.Request(url,callbackself.parse)breakfile.close()def parse(self, response):数据存储以及翻页操作item  MeituanItem()data  json.loads(response.body)item[data]dict()item[data]  datayield itemoffset  re.search(offset(\d),response.request.url).group(1)url  re.sub(offset\d,offsetstr(int(offset)15),response.request.url)yield scrapy.Request(url,callbackself.parse) 
运行scrapy runspider tutorial/spiders/Meituan_meishi.py 采集方案策略设计 首先大的地方我们想抓取某个数据源我们要知道大概有哪些路径可以获取到数据源基本上无外乎三种 PC端网站  针对移动设备响应式设计的网站也就是很多人说的 H5, 虽然不一定是H5  移动 App 
原则是能抓移动App的最好抓移动App如果有针对移动设备优化的网站就抓针对移动设备优化的网站最后考虑PC网站。因为移动 App 基本都是 API 很简单而移动设备访问优化的网站一般来讲都是结构简单清晰的 HTML而 PC 网站自然是最复杂的了针对 PC 端网站和移动网站的做法一样分析思路可以一起讲移动App单独分析。 网站类型的分析 
首先是网站类的使用的工具就是 Chrome建议用 Chrome 的隐身模式分析时不用频繁清除 cookie直接关闭窗口就可以了。 
具体操作步骤如下 输入网址后先不要回车确认右键选择审查元素然后点击网络记得要勾上preserve log选项因为如果出现上面提到过的重定向跳转之前的请求全部都会被清掉影响分析尤其是重定向时还加上了Cookie  接下来观察网络请求列表资源文件例如css图片基本都可以忽略第一个请求肯定就是该链接的内容本身所以查看源码确认页面上需要抓取的内容是不是在HTML标签里面很简单的方法找到自己要找的内容看到父节点然后再看源代码里面该父节点里面有没有内容如果没有那么一定是异步请求如果是非异步请求直接抓该链接就可以了。 分析异步请求按照网络列表略过资源文件然后点击各个请求观察是否在返回时包含想要的内容有几个方法  内容比较有特点例如人的属性信息物品的价格或者微博列表等内容直接观察可以判断是不是该异步请求  知道异步加载的内容节点或者父节点的class或者id的名称找到js代码阅读代码得到异步请求 确认异步请求之后就是要分析异步请求了简单的直接请求异步请求能得到数据但是有时候异步请求会有限制所以现在分析限制从何而来。 
针对分析对请求的限制思路是逆序方法。 先找到最后一个得到内容的请求然后观察headers先看post数据或者url的某个参数是不是都是已知数据或者有意义数据如果发现不确定的先带上只是更改某个关键字段例如pagecount看结果是不是会正常如果不正常比如多了个token或者某个字段明显被加密例如用户名密码那么接下来就要看JS的代码看到底是哪个函数进行了加密一般会是原生JS代码加密那么看到代码直接加密就行如果是类似RSA加密那么就要看公钥是从何而来如果是请求得到的那么就要往上分析请求另外如果是发现请求headers里面有陌生字段或者有Cookie也要往上看请求Cookie在哪一步设置的  接下来找到刚刚那个请求未知来源的信息例如Cookie或者某个加密需要的公钥等等看看上面某个请求是不是已经包含依次类推。 App 的分析 
App 类使用的工具是 Fidder手机和电脑在一个局域网内先用 Fidde r配置好端口然后手机设置代理ip 为电脑的 ip端口为设置的端口然后如果手机上请求网络内容时Fidder 会显示相应地请求那么就 ok 了分析的大体逻辑基本一致限制会相对少很多但是也有几种情况需要注意 
加密App有时候也有一些加密的字段这个时候,一般来讲都会进行反编译进行分析找到对应的代码片段逆推出加密方法gzip压缩或者base64编码base64编码的辨别度较高有时候数据被gzip压缩了不过Charles都是有自动解密的https证书有的https请求会验证证书, Fidder提供了证书可以在官网找到手机访问然后信任添加就可以。爬虫搜索策略 在爬虫系统中待抓取 URL 队列是很重要的一部分。待抓取 URL 队列中的 URL 以什么样的顺序排列也是一个很重要的问题因为这涉及到先抓取那个页面后抓取哪个页面。而决定这些 URL 排列顺序的方法叫做抓取策略。 1、 深度优先搜索策略顺藤摸瓜(Depth-First Search) 
即图的深度优先遍历算法。网络爬虫会从起始页开始一个链接一个链接跟踪下去处理完这条线路之后再转入下一个起始页继续跟踪链接。 2、 广度宽度优先搜索策略Breadth First Search 
宽度优先遍历策略的基本思路是将新下载网页中发现的链接直接插入待抓取URL队列的末尾。也就是指网络爬虫会先抓取起始网页中链接的所有网页然后再选择其中的一个链接网页继续抓取在此网页中链接的所有网页。 
有很多研究将广度优先搜索策略应用于聚焦爬虫中。其基本思想是认为与初始URL在一定链接距离内的网页具有主题相关性的概率很大。 广度优先搜索和深度优先搜索 
深度优先搜索算法涉及的是堆栈 
广度优先搜索涉及的是队列。 
堆栈(stacks)具有后进先出(last in first outLIFO)的特征 
队列(queue)是一种具有先进先出(first in first outLIFO)特征的线性数据结构 Scrapy是以广度优先还是深度优先进行爬取的呢 
默认情况下Scrapy使用 LIFO 队列来存储等待的请求。简单的说就是 深度优先顺序 。深度优先对大多数情况下是更方便的。如果您想以 广度优先顺序 进行爬取你可以设置以下的设定: 
DEPTH_PRIORITY  1
SCHEDULER_DISK_QUEUE  scrapy.squeue.PickleFifoDiskQueue
SCHEDULER_MEMORY_QUEUE  scrapy.squeue.FifoMemoryQueue 二叉树的深度优先遍历与广度优先遍历 [ C 实现 ] 
深度优先搜索算法Depth First Search是搜索算法的一种。是沿着树的深度遍历树的节点尽可能深的搜索树的分支。 
当节点v的所有边都己被探寻过搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。 
如果还存在未被发现的节点则选择其中一个作为源节点并重复以上过程整个进程反复进行直到所有节点都被访问为止。 如右图所示的二叉树 
A 是第一个访问的然后顺序是 B、D然后是 E。接着再是 C、F、G。 
那么怎么样才能来保证这个访问的顺序呢 
分析一下在遍历了根结点后就开始遍历左子树最后才是右子树。 
因此可以借助堆栈的数据结构由于堆栈是后进先出的顺序由此可以先将右子树压栈然后再对左子树压栈 
这样一来左子树结点就存在了栈顶上因此某结点的左子树能在它的右子树遍历之前被遍历。 
深度优先遍历代码片段 
//深度优先遍历
void depthFirstSearch(Tree root){stackNode * nodeStack;  //使用C的STL标准模板库nodeStack.push(root);Node *node;while(!nodeStack.empty()){node  nodeStack.top();printf(format, node-data);  //遍历根结点nodeStack.pop();if(node-rchild){nodeStack.push(node-rchild);  //先将右子树压栈}if(node-lchild){nodeStack.push(node-lchild);  //再将左子树压栈}}
} 
广度优先搜索算法Breadth First Search又叫宽度优先搜索或横向优先搜索。 
是从根节点开始沿着树的宽度遍历树的节点。如果所有节点均被访问则算法中止。 
如右图所示的二叉树A 是第一个访问的然后顺序是 B、C然后再是 D、E、F、G。 那么怎样才能来保证这个访问的顺序呢 
借助队列数据结构由于队列是先进先出的顺序因此可以先将左子树入队然后再将右子树入队。 
这样一来左子树结点就存在队头可以先被访问到。 
广度优先遍历代码片段 
//广度优先遍历
void breadthFirstSearch(Tree root){queueNode * nodeQueue;  //使用C的STL标准模板库nodeQueue.push(root);Node *node;while(!nodeQueue.empty()){node  nodeQueue.front();nodeQueue.pop();printf(format, node-data);if(node-lchild){nodeQueue.push(node-lchild);  //先将左子树入队}if(node-rchild){nodeQueue.push(node-rchild);  //再将右子树入队}}
} 
完整代码: 
/*** !--* File   : binarytree.h* Author : fancy* Email  : fancydeepinyeah.net* Date   : 2013-02-03* --!*/
#include stdio.h
#include stdlib.h
#include malloc.h
#include Stack
#include Queue
using namespace std;
#define Element char
#define format %ctypedef struct Node {Element data;struct Node *lchild;struct Node *rchild;
} *Tree;int index  0;  //全局索引变量//二叉树构造器,按先序遍历顺序构造二叉树
//无左子树或右子树用#表示
void treeNodeConstructor(Tree root, Element data[]){Element e  data[index];if(e  #){root  NULL;}else{root  (Node *)malloc(sizeof(Node));root-data  e;treeNodeConstructor(root-lchild, data);  //递归构建左子树treeNodeConstructor(root-rchild, data);  //递归构建右子树}
}//深度优先遍历
void depthFirstSearch(Tree root){stackNode * nodeStack;  //使用C的STL标准模板库nodeStack.push(root);Node *node;while(!nodeStack.empty()){node  nodeStack.top();printf(format, node-data);  //遍历根结点nodeStack.pop();if(node-rchild){nodeStack.push(node-rchild);  //先将右子树压栈}if(node-lchild){nodeStack.push(node-lchild);  //再将左子树压栈}}
}//广度优先遍历
void breadthFirstSearch(Tree root){queueNode * nodeQueue;  //使用C的STL标准模板库nodeQueue.push(root);Node *node;while(!nodeQueue.empty()){node  nodeQueue.front();nodeQueue.pop();printf(format, node-data);if(node-lchild){nodeQueue.push(node-lchild);  //先将左子树入队}if(node-rchild){nodeQueue.push(node-rchild);  //再将右子树入队}}
}/*** !--* File   : BinaryTreeSearch.h* Author : fancy* Email  : fancydeepinyeah.net* Date   : 2013-02-03* --!*/
#include binarytree.hint main() {//上图所示的二叉树先序遍历序列,其中用#表示结点无左子树或无右子树Element data[15]  {A, B, D, #, #, E, #, #, C, F,#, #, G, #, #};Tree tree;treeNodeConstructor(tree, data);printf(深度优先遍历二叉树结果: );depthFirstSearch(tree);printf(\n\n广度优先遍历二叉树结果: );breadthFirstSearch(tree);return 0;}