第二十天 异步爬虫(2)
今天计划用Python开发一套异步爬虫框架用来补充blog内容,学习项目及练习源码地址:
GitHub源码
在蜘蛛中提取想要的数据
lxml
通过lxml模块分析爬取到的页面数据,提取想要的内容。
封装一个selector类
from lxml import etree
from lxml.html import fromstring, tostring
from pyquery import PyQuery as pq
class Xpath(Selector):
def parse_detail(self, html):
d = etree.HTML(html)
try:
if self.attr is None:
result = None
if len(d.xpath(self.rule)) > 1:
result = [entry for entry in d.xpath(self.rule)]
else:
result = d.xpath(self.rule)
if self.r_type == 'elstr' and len(result) > 0:
return [tostring(el,'utf-8').decode('utf-8') for el in result]
elif self.r_type == 'text' and len(result) >0:
return [el.text for el in result]
else:
return result
return [entry.get(self.attr, None) for entry in d.xpath(self.rule)] if len(d.xpath(self.rule)) > 1 else \
d.xpath(self.rule)[0]
except IndexError:
return None
要点:
- lxml.etree 提供的xpath获取页面元素
-
tostring(el,'utf-8').decode('utf-8')
直接提取某元素内的html内容
在蜘蛛中使用:
async def parser(self,data):
try:
# print('jianshu parser',data)
title = Xpath('//section/h1/text()').parse_detail(data)[0]
content = Xpath('//*[@id="__next"]/div[1]/div/div/section[1]/article',r_type='elstr').parse_detail(data)[0]
except BaseException as e:
self.logger.error(e)
自此,已经完成了蜘蛛对页面的爬取,以及数据的解析。
让蜘蛛定时爬取
在crawler函数中回调自身
async def crawler(self):
await self.init_spiders()
workers = [asyncio.Task(self.worker(), loop=self.loop)
for _ in range(self.max_tasks)]
await self.q.join()
for w in workers:
w.cancel()
await asyncio.sleep(5 * 60)
await self.crawler() # 重新一直运行下去
注意:到目前为止,发现这样的方式有一点问题,不知道是否可以像nodejs一样可以尾回调,因为一直回调会导致嵌套过深的问题。
蜘蛛的启动
在启动中可以初始化一些辅助的服务,如mysql连击池等
def main(loop):
print('starting kospider server')
coros = [mysql.initpool(loop=loop), redis.init_pool(loop=loop)]
loop.run_until_complete(asyncio.gather(*coros))
engine = Engine(loop=loop)
engine.run()
event_loop = asyncio.get_event_loop()
try:
event_loop.run_until_complete(main(event_loop))
print('stoped kospider server')
except BaseException as e:
print('Main error',e)
finally:
event_loop.close() # 当轮训器关闭以后,所有没有执行完成的协成将全部关闭
明天正式将数据写入数据库,并在页面显示内容。
计划找一个能让蜘蛛定时执行的好方式。