折腾:
【未解决】用Python爬虫框架PySpider实现爬虫爬取百度热榜内容列表
期间,此处已经可以抓取到要的标题列表了。
现在希望单个页面能返回(一个列表中的)多个结果
此处不知道如何实现 每次返回单个结果
pyspider return 返回多个结果
竟然搜到的第一个是我自己的帖子
改为:
curResult = { # "url": response.url, "百度热榜标题": itemTitleStr, } # return curResult self.send_message(self.project_name, curResult, url=response.url)
结果:
终于可以返回多个结果了:
但是去Run后,发现列表中并没有我们要的结果
发现了,忘了加on_message了。。。
调试:
去运行:
问题依旧。结果还是没有。
还是参考:
去试试ResultDB
发现也不对,需要额外
resultdb = connect_database("<your resutldb connection url>")
此处不希望引入额外数据库。
好像可以多次调用on_result去保存?
后记:自己回复了:
好像是:url重复了?
那去使得url不重复试试?
不过,先确保Results中能看到这个 即使只有的 一个结果:
curResult = { # "url": response.url, "百度热榜标题": itemTitleStr, } return curResult # self.send_message(self.project_name, curResult, url=response.url) # def on_message(self, project, msg): # print("on_message: msg=", msg) # return msg
结果
调试时,正常,返回单个结果:
去看看Results中:
还是空的。
返回时加上url
curResult = { "url": response.url, "百度热榜标题": itemTitleStr, } return curResult
结果:
再看看Results
依旧是空。
删除项目重新创建试试
然后设置了RUNNING,再点击Run:
才会有结果:
那就正常了。
然后再去改造,返回多个结果:
# for eachItem in titleItemList: for curIdx, eachItem in enumerate(titleItemList): print("[%d] eachItem=%s" % (curIdx, eachItem)) itemTitleStr = eachItem.text() print("itemTitleStr=%s" % itemTitleStr) curUrl = "%s#%d" % (response.url, curIdx) print("curUrl=%s" % curUrl) curResult = { # "url": response.url, "url": curUrl, "百度热榜标题": itemTitleStr, } return curResult
结果:
但是试了半天,保存的结果,始终没能更新
url没有变成调试时候的:
https://www.baidu.com/#0
算了,再去重新新建?
好像也不合适。
算了,参考之前的逻辑和官网文档
想办法,尽快删除原有项目:
pyspider scheduler --delete-time=30
重新运行:
✘ xxx@xxx ~/dev/crifan/python/demo_spider pyspider scheduler --delete-time=30 [I 200731 14:45:16 scheduler:647] scheduler starting... [I 200731 14:45:16 scheduler:782] scheduler.xmlrpc listening on 0.0.0.0:23333 [I 200731 14:45:16 scheduler:126] project crawlBaiduHotList_PySpider updated, status:STOP, paused:False, 0 tasks [I 200731 14:45:16 scheduler:126] project crawlBaiduHotList_PySpider_0731_1436 updated, status:DEBUG, paused:False, 0 tasks [I 200731 14:45:16 scheduler:965] select crawlBaiduHotList_PySpider_0731_1436:_on_get_info data:,_on_get_info [I 200731 14:45:16 scheduler:586] in 5m: new:0,success:0,retry:0,failed:0 [W 200731 14:45:16 scheduler:613] deleting project: crawlBaiduHotList_PySpider!
立刻就删除了之前的旧项目。
但是无法通过
去打开UI了。
所以换成配置文件
config.json
{ "webui": { "port": 5000, "need-auth": false }, "scheduler": { "delete_time": 30 } }
运行调用效果:
pyspider -c use_python_spider_framework/config.json [I 200731 14:48:06 result_worker:49] result_worker starting... phantomjs fetcher running on port 25555 [I 200731 14:48:06 processor:211] processor starting... [I 200731 14:48:06 scheduler:647] scheduler starting... [I 200731 14:48:06 tornado_fetcher:638] fetcher starting... [I 200731 14:48:06 scheduler:782] scheduler.xmlrpc listening on 127.0.0.1:23333 [I 200731 14:48:06 scheduler:126] project crawlBaiduHotList_PySpider_0731_1436 updated, status:DEBUG, paused:False, 0 tasks [I 200731 14:48:06 scheduler:965] select crawlBaiduHotList_PySpider_0731_1436:_on_get_info data:,_on_get_info [I 200731 14:48:06 scheduler:586] in 5m: new:0,success:0,retry:0,failed:0 [I 200731 14:48:06 tornado_fetcher:188] [200] crawlBaiduHotList_PySpider_0731_1436:_on_get_info data:,_on_get_info 0s [D 200731 14:48:06 project_module:145] project: crawlBaiduHotList_PySpider_0731_1436 updated. [I 200731 14:48:06 processor:202] process crawlBaiduHotList_PySpider_0731_1436:_on_get_info data:,_on_get_info -> [200] len:12 -> result:None fol:0 msg:0 err:None [I 200731 14:48:06 scheduler:360] crawlBaiduHotList_PySpider_0731_1436 on_get_info {'min_tick': 0, 'retry_delay': {}, 'crawl_config': {}} [I 200731 14:48:06 app:76] webui running on 0.0.0.0:5000
然后新建项目后,结果对了:
url是:
“https://www.baidu.com/#0”
然后继续试试message的效果:
print("curUrl=%s" % curUrl) curResult = { # "url": response.url, "url": curUrl, "百度热榜标题": itemTitleStr, } # return curResult # self.send_message(self.project_name, curResult, url=response.url) self.send_message(self.project_name, curResult, url=curUrl) def on_message(self, project, msg): print("on_message: msg=", msg) return msg
结果:
问题依旧。还是只有一个。
作者自己说了,就是用on_message
def detail_page(self, response): for i, each in enumerate(response.json['products']): self.send_message(self.project_name, { "name": each['name'], 'price': each['prices'], }, url="%s#%s" % (response.url, i)) def on_message(self, project, msg): return msg
但是自己此处好像就是没生效?
重新删除项目再试试
就可以了:
点击CSV去导出:
url,url,百度热榜标题,... https://www.baidu.com/#5,https://www.baidu.com/#5,2020ChinaJoy逛展指南,{} https://www.baidu.com/#4,https://www.baidu.com/#4,特朗普改口称不想推迟选举,{} https://www.baidu.com/#3,https://www.baidu.com/#3,19岁贫困男孩高考后查出白血病,{} https://www.baidu.com/#2,https://www.baidu.com/#2,赵正永一审被判死缓,{} https://www.baidu.com/#1,https://www.baidu.com/#1,阿云嘎粉丝后援会闭站,{} https://www.baidu.com/#0,https://www.baidu.com/#0,北斗正式开通,{}
就得到我们要的数据了。
以列表形式预览:
当然,如果不想要url,则可以用VSCode列编辑模式去删除掉
或者用excel打开,删除不要的第一列url和最后一列 … 也可以。
再去修改代码,去掉返回的url字段:
curResult = { # "url": response.url, # "url": curUrl, "百度热榜标题": itemTitleStr, }
结果:
调试:
运行:
CSV:
预览效果:
即可。
【总结】
此处,单个页面的response处理函数中,想要返回多个结果
之前写法:
for eachItem in titleItemList: print("eachItem=%s" % eachItem) itemTitleStr = eachItem.text() print("itemTitleStr=%s" % itemTitleStr) return { "百度热榜标题": itemTitleStr }
只能返回单个结果。
后来改为message方式:
curResult = { "url": response.url, "百度热榜标题": itemTitleStr, } # return curResult self.send_message(self.project_name, curResult, url=response.url) def on_message(self, project, msg): print("on_message: msg=", msg) return msg
仍然只能返回单个项目
原因:url每次都是一样的,后续的由于url重复而导致被忽略,没有被保存下来
解决办法:确保每次url不同
方式之一:给url后面加上#xxx 其中xxx是任意值,确保不同即可。
常用做法,用循环的index或number
比如此处:
# for eachItem in titleItemList: for curIdx, eachItem in enumerate(titleItemList): print("[%d] eachItem=%s" % (curIdx, eachItem)) itemTitleStr = eachItem.text() print("itemTitleStr=%s" % itemTitleStr) curUrl = "%s#%d" % (response.url, curIdx) print("curUrl=%s" % curUrl) curResult = { # "url": response.url, # "url": curUrl, "百度热榜标题": itemTitleStr, } # return curResult # self.send_message(self.project_name, curResult, url=response.url) self.send_message(self.project_name, curResult, url=curUrl) def on_message(self, project, msg): print("on_message: msg=", msg) return msg
确保了url不同,就可以保存出来了。
注意:
每次代码改动,按道理重新运行,即可产生新结果,但是貌似由于此处PySpider有bug了?
无论怎么尝试,都无法重新生成结果,最后无奈只能删除旧项目,重建新项目,才能得到最新结果。很是郁闷。