使用Python进行Web-scraping JavaScript页面

15 浏览
0 Comments

使用Python进行Web-scraping JavaScript页面

我正在尝试开发一个简单的网络爬虫程序。我想提取没有HTML标记的纯文本。我的代码适用于纯静态HTML,但当内容是由嵌入在页面中的JavaScript生成时,它就不起作用了。

特别是,当我使用urllib2.urlopen(request)读取页面内容时,它不显示任何由JavaScript代码添加的内容,因为该代码未在任何地方执行。通常它将由Web浏览器运行,但这不是我的程序的一部分。

我如何从我的Python代码中访问此动态内容?


有关专门针对Scrapy的答案,请参见Can scrapy be used to scrape dynamic content from websites that are using AJAX?

admin 更改状态以发布 2023年5月24日
0
0 Comments

我们没有得到正确的结果,因为任何由JavaScript生成的内容都需要在DOM上呈现。当我们获取HTML页面时,我们获取最初未经JavaScript修改的DOM。

因此,在爬取页面之前,我们需要呈现JavaScript内容。

由于selenium已经在这个帖子中多次提到(还提到了它有时会变慢),我将列出另外两种可能的解决方案。


解决方案1: 这是一个非常好的教程,介绍了如何使用Scrapy爬取由JavaScript生成的内容,我们将遵循这个教程。

我们将需要:

  1. 在我们的计算机上安装Docker。这是迄今为止与其他解决方案相比的一个优点,因为它利用了一个独立于操作系统的平台。

  2. 按照我们相应操作系统的指示安装Splash
    引用Splash文档:

    Splash是一个JavaScript渲染服务。这是一个带有HTTP API的轻量级网络浏览器,使用Python 3,并使用Twisted和QT5实现。

    本质上,我们将使用Splash来呈现由JavaScript生成的内容。

  3. 运行Splash服务器:sudo docker run -p 8050:8050 scrapinghub/splash

  4. 安装scrapy-splash插件:pip install scrapy-splash

  5. 假设我们已经创建了一个Scrapy项目(如果没有,让我们创建一个),我们将按照指南更新settings.py

    然后进入您的Scrapy项目的settings.py,并设置这些中间件:

    DOWNLOADER_MIDDLEWARES = {
          'scrapy_splash.SplashCookiesMiddleware': 723,
          'scrapy_splash.SplashMiddleware': 725,
          'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
    }
    

    Splash服务器的URL(如果您使用的是Win或OSX,则应为Docker机器的URL:如何从主机获取Docker容器的IP地址?):

    SPLASH_URL = 'http://localhost:8050'
    

    最后,您还需要设置这些值:

    DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
    HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
    

  6. 最后,我们可以使用SplashRequest

    在正常的爬虫程序中,您有请求对象(Request objects),您可以使用它们打开URL。如果要打开的页面包含JS生成的数据,则必须使用SplashRequest(或Splas hFormRequest)来呈现页面。以下是一个简单的例子:

    class MySpider(scrapy.Spider):
        name = "jsscraper"
        start_urls = ["http://quotes.toscrape.com/js/"]
        def start_requests(self):
            for url in self.start_urls:
            yield SplashRequest(
                url=url, callback=self.parse, endpoint='render.html'
            )
        def parse(self, response):
            for q in response.css("div.quote"):
            quote = QuoteItem()
            quote["author"] = q.css(".author::text").extract_first()
            quote["quote"] = q.css(".text::text").extract_first()
            yield quote
    

    SplashRequest将URL呈现为html并返回响应,您可以在回调(parse)方法中使用该响应。

  7. 解决方案2:目前(2018年5月)先称之为试验性解决方案...
    此解决方案仅适用于Python 3.6版本(目前)。

    您是否知道requests模块(不知道的人有吗)?
    现在,它有了一个网页抓取小伙伴:requests-HTML

    该库旨在使解析HTML(例如从网页抓取)尽可能简单和直观。

    1. 安装requests-html: pipenv install requests-html

    2. 向页面链接发送请求:

      from requests_html import HTMLSession
      session = HTMLSession()
      r = session.get(a_page_url)
      

    3. 渲染响应以获取JavaScript生成的内容:

      r.html.render()
      

    最后,该模块似乎提供抓取功能
    或者,我们可以尝试使用精心编写的BeautifulSoup方式,使用我们刚刚渲染的r.html对象。

0
0 Comments

编辑于2021年9月:phantomjs也不再维护了

编辑于2017年12月30日:此答案出现在Google搜索结果的顶部,因此我决定更新它。旧答案仍在文末。

dryscape已不再维护,而dryscape开发人员推荐的库仅支持Python 2。我发现使用Selenium的Python库作为web驱动器和Phantom JS快速并且易于完成工作。

安装Phantom JS后,确保phantomjs二进制文件在当前路径中可用:

phantomjs --version
# result:
2.1.1

#示例
例如,我创建了一个带有以下HTML代码的示例页面。(链接):




  
  Javascript scraping test


  

No javascript support

没有JavaScript时,它会显示:不支持JavaScript,而有JavaScript时:耶!支持JavaScript

#无JS支持的爬虫:

import requests
from bs4 import BeautifulSoup
response = requests.get(my_url)
soup = BeautifulSoup(response.text)
soup.find(id="intro-text")
# Result:

No javascript support

#有JS支持的爬虫:

from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get(my_url)
p_element = driver.find_element_by_id(id_='intro-text')
print(p_element.text)
# result:
'Yay! Supports javascript'


您还可以使用Python库dryscrape来抓取JavaScript驱动的网站。

#有JS支持的爬虫:

import dryscrape
from bs4 import BeautifulSoup
session = dryscrape.Session()
session.visit(my_url)
response = session.body()
soup = BeautifulSoup(response)
soup.find(id="intro-text")
# Result:

Yay! Supports javascript

0