Joynet示例:知乎爬虫(搜索关键字相关回答,并下载其中的---图(mei)片(nv))
先贴爬虫程序下载地址:http://pan.baidu.com/s/1c2lxl1e
下载解压后 可直接运行 其中的 run.bat;或者你手动打开命令行执行:Joynet examples\SpiderZhihu.lua。
大家不妨先下载下来玩一玩(可以修改配置,在examples目录下的ZhihuConfig.lua,添加感兴趣的关键字)
这个爬虫程序作为我写的Lua网络库 Joynet 的示例。
主要使用了异步Connect/HTTP/HTTPS 访问知乎搜索页面,譬如 https://www.zhihu.com/search?type=content&q=test 就是搜索 test 相关的问题。
拿到它的response 采用字符串搜索其中的各个question的url 地址。然后进行访问。在拿到question的页面内容后查找其中的图片相关url地址,然后再访问图片服务器下载到本地。
整个爬虫的代码在:https://github.com/IronsDu/Joynet/blob/master/examples/SpiderZhihu.lua#L118。
一点问题:一般而言,开多个协程(链接)的话速度会提高很多。但在知乎爬虫中(访问知乎)并没有体现,反而更慢。我猜测与同时开多个链接到知乎时,知乎服务器做了速度限制。
(而且会给我返回部分 429 错误码···)
(我不知道该如何优化并发请求策略,以达到速度最快,且不会让服务器给我返回错误)
如果你无法访问github,可以看下面我复制过来的爬虫源码:
package.path = "./?.lua;./src/?.lua;./libs/?.lua;"
local ZhihuConfig = require "examples.ZhihuConfig"
local TcpService = require "TcpService"
local HttpClient = require "HttpClient"
local picTypes = {"png", "jpg", "jpeg"}
local requestedPicNum = 0
local requestdPic = {} --当前已经发出请求的图片集合
local totalPicNum = 0 --当前已经完成请求的图片数量
local zhihuAddres = GetIPOfHost("www.zhihu.com")
local picAddres = {} --pic http 服务器ip地址集合,key 为域名
UtilsCreateDir(ZhihuConfig.saveDir)
local function singleCo(f)
-- 不开启协程,因为经过测试发现,同时开多个链接到zhihu时,速度反而下降,通过访问百度进行对比,发现可能是zhihu服务器(故意)设置锁导致的
if false then
coroutine_start(function ()
f()
end)
else
f()
end
end
-- 访问图片地址,下载成功则保存到文件
local function requestPic(clientService, pic_url, dirname, qoffset)
local s,e = string.find(pic_url, "https:%/%/")
local _,hostEnd = string.find(pic_url, "%.com")
local host = string.sub(pic_url, e+1, hostEnd)
local url = string.sub(pic_url, hostEnd+1, string.len(pic_url))
print(os.date().." start request :"..pic_url)
if picAddres[host] == nil then
picAddres[host] = GetIPOfHost(host)
end
local response = HttpClient.Request(clientService, picAddres[host], 443, true, "GET", url, host)
if response ~= nil then
local f = io.open(ZhihuConfig.saveDir.."\\"..dirname.."\\"..qoffset.."\\"..string.sub(url, 2, string.len(url)), "w+b")
f:write(response)
f:flush()
f:close()
f=nil
print(os.date().." recv pic :"..pic_url.." success")
totalPicNum = totalPicNum + 1
else
print(os.date().." recv pic :"..pic_url.." failed")
end
end
-- 访问问题页面
local function requestQuestion(clientService, question_url, dirname, qoffset)
UtilsCreateDir(ZhihuConfig.saveDir.."\\"..dirname)
UtilsCreateDir(ZhihuConfig.saveDir.."\\"..dirname.."\\"..qoffset)
local fname = ZhihuConfig.saveDir.."\\"..dirname.."\\".."questions_address.txt"
print(fname)
local f = io.open(fname, "a+")
f:write(question_url.."\r\n")
f:flush()
f:close()
f=nil
local response = HttpClient.Request(clientService, zhihuAddres, 443, true, "GET", question_url, "www.zhihu.com")
if response ~= nil then
for _,picType in ipairs(picTypes) do
local pos = 1
while true do
--TODO (优化匹配代码以及图片后缀)
--查找此问题页面中的图片地址
local s, e = string.find(response, "https:%/%/pic%d.zhimg.com%/%w*%_r%."..picType, pos)
if s ~= nil then
local pic_url = string.sub(response, s, e)
if not requestdPic[pic_url] then
requestdPic[pic_url] = true
requestedPicNum = requestedPicNum + 1
singleCo(function ()
--访问图片
requestPic(clientService, pic_url, dirname, qoffset)
end)
end
pos = e
else
print("no more pic in question "..question_url)
break
end
end
end
end
end
local function urlEnCode(w)
local pattern="[^%w%d%._%-%* ]"
s=string.gsub(w,pattern,function(c)
local c=string.format("%%%02X",string.byte(c))
return c
end)
s=string.gsub(s," ","+")
return s
end
local isAllCompleted = false
function userMain()
local clientService = TcpService:New()
clientService:createService()
coroutine_start(function()
-- 访问知乎搜索页面,搜索配置的关键字的相关问题
for k,v in pairs(ZhihuConfig.querys) do
for i=1,v.count do
local response = HttpClient.Request(clientService, zhihuAddres, 80, false, "GET", "/search", "www.zhihu.com", {type="content",q=urlEnCode(v.q), offset=v.startOffset+10*(i-1)})
local pos = 1
if response ~= nil then
while true do
--查找问题页面地址
local s, e = string.find(response, "\"%/question%/%d*\"", pos)
if s ~= nil then
pos = e
local question_url = string.sub(response, s+1 , e-1)
print("request question_url :"..question_url)
singleCo(function ()
--访问问题页面
requestQuestion(clientService, question_url, v.dirname, v.startOffset+10*(i-1))
end)
else
print("no more question, will break")
break
end
end
end
end
end
isAllCompleted = true
end)
coroutine_start(function ()
while true do
coroutine_sleep(coroutine_running(), 1000)
print("Current Completed Pic Num : "..totalPicNum)
print("Current requested pic num: "..requestedPicNum)
if isAllCompleted then
print("all pic completed, you can close process")
break
end
end
end)
end
coroutine_start(function ()
userMain()
end)
while true
do
CoreDD:loop()
while coroutine_pengdingnum() > 0
do
coroutine_schedule()
end
end
Joynet示例:知乎爬虫(搜索关键字相关回答,并下载其中的---图(mei)片(nv))的更多相关文章
- C#分析搜索引擎URL得到搜索关键字,并判断页面停留时间以及来源页面
前台代码: var start; var end; var state; var lasturl = document.referrer; start = new Date($.ajax({ asyn ...
- C# 分析搜索引擎url 得到搜索关键字
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- java使用itex读取pdf,并搜索关键字,为其盖章
导读:近期要做一个根据关键字定位pdf的盖章位置的相关需求,其中关键字可配置多个(包含pdf文档中可能不存在的关键字),当页面显示盖章完成时,打开pdf显示已经损坏. 排查后发现,当itext搜索的关 ...
- 【2022知乎爬虫】我用Python爬虫爬了2300多条知乎评论!
您好,我是 @马哥python说,一枚10年程序猿. 一.爬取目标 前些天我分享过一篇微博的爬虫: https://www.cnblogs.com/mashukui/p/16414027.html 但 ...
- Java爬虫搜索原理实现
permike 原文 Java爬虫搜索原理实现 没事做,又研究了一下爬虫搜索,两三天时间总算是把原理闹的差不多了,基本实现了爬虫搜索的原理,本次实现还是俩程序,分别是按广度优先和深度优先完成的,广度优 ...
- 在 Angular 中实现搜索关键字高亮
在 Angular 中,我们不应该试图直接修改 DOM 的内容,当需要更新 DOM 内容的时候,应该修改的其实是我们的数据模型,也就是 $scope 中的数据,Angular 会帮助我们将修改之后的数 ...
- 仿百度壁纸客户端(五)——实现搜索动画GestureDetector手势识别,动态更新搜索关键字
仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Frag ...
- google 搜索关键字技巧
google 搜索关键字技巧 来源 https://www.cnblogs.com/qiudabai/articles/9143328.html inurl: 用于搜索网页上包含的URL. 这个语法 ...
- 帝国cms搜索关键字调用标签(showsearch)怎么用
前面ytkah介绍了如何让帝国CMS7.2搜索模板支持动态标签调用,现在我们来说说怎么调用帝国cms搜索关键字调用标签(showsearch).在帝国cms后台那边的使用方法:[showsearch] ...
随机推荐
- C#UDP同步实例
差不多有一个礼拜总算有点进步. 代码很简单,只是为了实现功能. 网络上的资源是很多,除了不能用的,就是抄来抄去,是在乏味浪费时间. 说一下代码背景:实现的功能是发送端发送消息,接收端接收后立即响应,发 ...
- POJ 2398 Toy Storage(计算几何,叉积判断点和线段的关系)
Toy Storage Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3146 Accepted: 1798 Descr ...
- HTTP中缓存相关
1.客户端如何区分缓存命中和未命中 两种情况下,返回的状态码都是200,客户端有一个方法可以判断,就是使用Date首部,将Date首部与当前时间进行比较,如果响应中时间日期值比较早,客户端可以认为这是 ...
- POJ 2378 Tree Cutting (DFS)
题目链接:http://poj.org/problem?id=2378 一棵树,去掉一个点剩下的每棵子树节点数不超过n/2.问有哪些这样的点,并按照顺序输出. dfs回溯即可. //#pragma c ...
- C# JackLib系列之Form窗体的ShowWithoutActivation属性及其作用
代码改变世界! 如果要显示顶级窗口,但又不希望由于将输入焦点从当前窗口移开而中断用户的工作,请使用此属性.它可以是一个信息性弹出窗口或浮动窗口,如“画图”应用程序中的“工具”调色板. 由于此属性为只读 ...
- SqlAgent备份脚本
) ) set @dbname='emcp' set @back_path= 'e:\'+@dbname+'\'+@dbname ),) )) )) )) +'.bak' exec('use ['+@ ...
- spring+jpg环境下,spring实现文件下载web实现通用的文件下载方法
jar包复制到WEB-INF 文件夹lib下: commons-io-1.3.2.jar public static String download(HttpServletRequest reques ...
- 11.聚合(Aggregation)
聚合关系是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系,此时整体与部分之间是可分离的,它们可以具有各自的生命周期.比如计算机与CPU.公司与员工的关系等.表现在代码层面,和关联关 ...
- js 原型的内存分析
使用构造器的弊端:http://www.cnblogs.com/a757956132/p/5258897.html 示例 将行为设置为全局的行为,如果将所有的方法都设计为全局函数的时候, 这个函数就可 ...
- xx.exe 中的 0x7c92e4df 处最可能的异常: 0xC0000008: An invalid handle was specified
今天遇到个超级奇怪的问题,昨天还好端端的程序,今天用VS打开后,在关闭主窗口的时候居然弹出错误提示:xx.exe 中的 0x7c92e4df 处最可能的异常: "0xC0000008: An ...