IT帮

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 27|回复: 5

Scrapy爬虫框架之Puppeteer渲染

[复制链接]

10

主题

15

帖子

18

积分

小学生

Rank: 1

热心值
1
IT币
76
贡献值
0
QQ
发表于 2020-6-10 17:40:38 | 显示全部楼层 |阅读模式

Puppeteer 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包,用来模拟 Chrome 浏览器的运行。
为了爬取js渲染的html页面,我们需要用浏览器来解析js后生成html。在scrapy中可以利用pyppeteer来实现对应功能。
我们需要新建项目中middlewares.py文件(./项目名/middlewares.py)
import websocketsfrom scrapy.http import HtmlResponsefrom logging import getLoggerimport asyncioimport pyppeteerimport loggingfrom concurrent.futures._base import TimeoutErrorimport base64import sysimport randompyppeteer_level = logging.WARNINGlogging.getLogger('websockets.protocol').setLevel(pyppeteer_level)logging.getLogger('pyppeteer').setLevel(pyppeteer_level)PY3 = sys.version_info[0] >= 3def base64ify(bytes_or_str):    if PY3 and isinstance(bytes_or_str, str):        input_bytes = bytes_or_str.encode('utf8')    else:        input_bytes = bytes_or_str    output_bytes = base64.urlsafe_b64encode(input_bytes)    if PY3:        return output_bytes.decode('ascii')    else:        return output_bytesclass ProxyMiddleware(object):    USER_AGENT = open('useragents.txt').readlines()    def process_request(self, request, spider):        # 代理服务器        proxyHost = "t.16yun.cn"亿牛云代理www.16yun.cn        proxyPort = "31111"        # 代理隧道验证信息        proxyUser = "username"        proxyPass = "password"        request.meta['proxy'] = "http://{0}:{1}".format(proxyHost, proxyPort)        # 添加验证头        encoded_user_pass = base64ify(proxyUser + ":" + proxyPass)        request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass        # 设置IP切换头(根据需求)        tunnel = random.randint(1, 10000)        request.headers['Proxy-Tunnel'] = str(tunnel)        request.headers['User-Agent'] = random.choice(self.USER_AGENT)class PyppeteerMiddleware(object):    def __init__(self, **args):        """        init logger, loop, browser        :param args:        """        self.logger = getLogger(__name__)        self.loop = asyncio.get_event_loop()        self.browser = self.loop.run_until_complete(            pyppeteer.launch(headless=True))        self.args = args    def __del__(self):        """        close loop        :return:        """        self.loop.close()    def render(self, url, retries=1, script=None, wait=0.3, scrolldown=False, sleep=0,               timeout=8.0, keep_page=False):        """        render page with pyppeteer        :param url: page url        :param retries: max retry times        :param script: js script to evaluate        :param wait: number of seconds to wait before loading the page, preventing timeouts        :param scrolldown: how many times to page down        :param sleep: how many long to sleep after initial render        :param timeout: the longest wait time, otherwise raise timeout error        :param keep_page: keep page not to be closed, browser object needed        :param browser: pyppetter browser object        :param with_result: return with js evaluation result        :return: content, [result]        """        # define async render        async def async_render(url, script, scrolldown, sleep, wait, timeout, keep_page):            try:                # basic render                page = await self.browser.newPage()                await asyncio.sleep(wait)                response = await page.goto(url, options={'timeout': int(timeout * 1000)})                if response.status != 200:                    return None, None, response.status                result = None                # evaluate with script                if script:                    result = await page.evaluate(script)                # scroll down for {scrolldown} times                if scrolldown:                    for _ in range(scrolldown):                        await page._keyboard.down('PageDown')                        await asyncio.sleep(sleep)                else:                    await asyncio.sleep(sleep)                if scrolldown:                    await page._keyboard.up('PageDown')                # get html of page                content = await page.content()                return content, result, response.status            except TimeoutError:                return None, None, 500            finally:                # if keep page, do not close it                if not keep_page:                    await page.close()        content, result, status = [None] * 3        # retry for {retries} times        for i in range(retries):            if not content:                content, result, status = self.loop.run_until_complete(                    async_render(url=url, script=script, sleep=sleep, wait=wait,                                 scrolldown=scrolldown, timeout=timeout, keep_page=keep_page))            else:                break        # if need to return js evaluation result        return content, result, status    def process_request(self, request, spider):        """        :param request: request object        :param spider: spider object        :return: HtmlResponse        """        if request.meta.get('render'):            try:                self.logger.debug('rendering %s', request.url)                html, result, status = self.render(request.url)                return HtmlResponse(url=request.url, body=html, request=request, encoding='utf-8',                                    status=status)            except websockets.exceptions.ConnectionClosed:                pass    @classmethod    def from_crawler(cls, crawler):        return cls(**crawler.settings.get('PYPPETEER_ARGS', {}))


然后修改项目配置文件 (./项目名/settings.py)
DOWNLOADER_MIDDLEWARES = {        'scrapypyppeteer.middlewares.PyppeteerMiddleware': 543,        'scrapypyppeteer.middlewares.ProxyMiddleware': 100,            }



  然后我们运行程序

ITbang.Net是一个IT教程分享社区!

寻找论坛资源请善用论坛搜索功能,这样会为你节约不少学习时间;

论坛资源如有过期链接失效等,请到教程反馈区发帖反馈,我们会为您良好的行为点赞加分!

回复

使用道具 举报

0

主题

58

帖子

36

积分

小学生

Rank: 1

热心值
0
IT币
-1
贡献值
0
发表于 2020-6-13 15:54:57 | 显示全部楼层
不知该说些什么。。。。。。就是谢谢

ITbang.Net是一个IT教程分享社区!

寻找论坛资源请善用论坛搜索功能,这样会为你节约不少学习时间;

论坛资源如有过期链接失效等,请到教程反馈区发帖反馈,我们会为您良好的行为点赞加分!

回复

使用道具 举报

0

主题

63

帖子

0

积分

小学生

Rank: 1

热心值
0
IT币
0
贡献值
0
发表于 2020-6-13 22:42:17 | 显示全部楼层
没看完~~~~~~ 先回复换一下帖子,我是好学生

ITbang.Net是一个IT教程分享社区!

寻找论坛资源请善用论坛搜索功能,这样会为你节约不少学习时间;

论坛资源如有过期链接失效等,请到教程反馈区发帖反馈,我们会为您良好的行为点赞加分!

回复

使用道具 举报

0

主题

62

帖子

22

积分

小学生

Rank: 1

热心值
12
IT币
33
贡献值
1
发表于 2020-6-14 18:28:11 | 显示全部楼层
支持ITbang_net,看帖回帖是美德!

ITbang.Net是一个IT教程分享社区!

寻找论坛资源请善用论坛搜索功能,这样会为你节约不少学习时间;

论坛资源如有过期链接失效等,请到教程反馈区发帖反馈,我们会为您良好的行为点赞加分!

回复

使用道具 举报

0

主题

61

帖子

36

积分

VIP

Rank: 8Rank: 8

热心值
0
IT币
-1
贡献值
0
发表于 2020-6-14 19:39:43 | 显示全部楼层
路过,学习下

ITbang.Net是一个IT教程分享社区!

寻找论坛资源请善用论坛搜索功能,这样会为你节约不少学习时间;

论坛资源如有过期链接失效等,请到教程反馈区发帖反馈,我们会为您良好的行为点赞加分!

回复

使用道具 举报

0

主题

69

帖子

19

积分

小学生

Rank: 1

热心值
10
IT币
22
贡献值
3
发表于 2020-6-17 23:41:13 | 显示全部楼层
感谢分享资源。。。

ITbang.Net是一个IT教程分享社区!

寻找论坛资源请善用论坛搜索功能,这样会为你节约不少学习时间;

论坛资源如有过期链接失效等,请到教程反馈区发帖反馈,我们会为您良好的行为点赞加分!

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
IT帮论坛所发布的一切视频资源、工具软件和网络技术相关的文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该资源,请支持正版软件,购买注册,得到更好的正版服务。

Mail To:Service@ITbang.Net

QQ|Archiver|手机版|小黑屋|IT帮社区 ( 冀ICP备19002104号-2 )

GMT+8, 2020-7-15 20:16 , Processed in 0.058449 second(s), 24 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表