Skip to content

Instantly share code, notes, and snippets.

@sxfmol
Last active March 28, 2023 03:26
Show Gist options
  • Save sxfmol/40b06d0d16ef4c880e537648844d2e83 to your computer and use it in GitHub Desktop.
Save sxfmol/40b06d0d16ef4c880e537648844d2e83 to your computer and use it in GitHub Desktop.
作为Scrapy架构师,我会使用以下方法来进行爬取任务的调度和自动化运维:
使用调度器(Scheduler):Scrapy有一个内置的调度器,可以控制爬虫程序的运行。您可以使用调度器设置爬虫的开始时间和结束时间,以及在何时发送请求。此外,您还可以设置调度器,以避免爬虫程序在同一时间内发送太多请求而被网站禁止访问。
使用自动化重试机制:如果您的爬虫程序在爬取数据时出现问题,例如无法连接到网站,您可以设置一个自动化重试机制,该机制将在一定时间内重试该任务。如果重试多次仍然失败,则将任务标记为失败并通知您。
使用监控和报警系统:为了确保爬虫程序的正常运行,您可以设置监控和报警系统。该系统将监视爬虫程序的运行状况,并在发现问题时自动发送通知给您。这样,您就可以及时采取行动,解决问题并确保程序的正常运行。
自动化部署和升级:为了简化爬虫程序的部署和升级过程,您可以使用自动化工具,例如Ansible、Jenkins等。这些工具可以帮助您自动化地部署和升级爬虫程序,从而节省时间和精力。
综上所述,使用调度器、自动化重试机制、监控和报警系统以及自动化部署和升级工具,可以帮助您有效地进行爬取任务的调度和自动化运维。
在Scrapy中,response对象是对HTTP响应的封装。response对象提供了一些方法和属性来访问响应的信息,如状态码、头部、正文和请求等。其中,request和follow方法是常用的方法之一。
request(url, callback=None, method='GET', headers=None, body=None, cookies=None, meta=None, encoding='utf-8', priority=0, dont_filter=False, errback=None) 方法可以通过一个新的请求继续爬取,它会返回一个新的请求对象,可以使用callback参数指定处理该请求的回调函数。
另外一个常用的方法是follow(url, callback=None, **kwargs),它可以从当前的响应中提取链接并创建一个新的请求。使用callback参数指定处理该请求的回调函数。
在Scrapy中,follow方法可以从当前响应中提取链接并创建一个新的请求。follow方法的详细参数如下:
url_or_request(必填):要跟进的URL或请求对象(例如Request对象)。
callback(可选):处理响应的回调函数。如果未指定,则默认为当前解析函数。
method(可选):请求的HTTP方法。默认为GET。
headers(可选):请求的头部。
body(可选):请求的主体。
cookies(可选):请求的cookies。
meta(可选):包含在请求中的元数据。可以用来传递额外的数据。
encoding(可选):响应的编码。默认为utf-8。
priority(可选):请求的优先级。默认为0。
dont_filter(可选):如果为True,则在去重时不考虑此请求。默认为False。
errback(可选):处理请求失败的回调函数。
@sxfmol
Copy link
Author

sxfmol commented Mar 25, 2023

模拟爬取
场景:scrapy 爬取数据,涉及到一个页面中的图表数据,有多个下拉列表,不同的下拉列表项对应不同的数据,如何爬取这个数据
方案:对于这种需要通过下拉列表来选择不同的数据的网页,可以考虑使用 Scrapy 搭配 Selenium 来实现。

具体步骤如下:

安装 Scrapy 和 Selenium:
Copy code
pip install scrapy
pip install selenium
配置 Selenium 的 webdriver,这里以 Chrome 为例:
python
Copy code
from selenium import webdriver

配置 Chrome 的 webdriver 路径

driver_path = '/path/to/chromedriver'

配置 Chrome options

chrome_options = webdriver.ChromeOptions()

使用 headless 模式(可选)

chrome_options.add_argument('--headless')

实例化 Chrome webdriver

driver = webdriver.Chrome(driver_path, options=chrome_options)
编写 Scrapy 的 Spider,使用 Selenium 的 webdriver 来模拟点击下拉列表和获取数据:
python
Copy code
import scrapy
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class MySpider(scrapy.Spider):
name = "my_spider"
start_urls = ['http://example.com']

def __init__(self):
    # 配置 Chrome 的 webdriver 路径
    self.driver_path = '/path/to/chromedriver'

    # 配置 Chrome options
    self.chrome_options = webdriver.ChromeOptions()

    # 使用 headless 模式(可选)
    self.chrome_options.add_argument('--headless')

    # 实例化 Chrome webdriver
    self.driver = webdriver.Chrome(self.driver_path, options=self.chrome_options)

def parse(self, response):
    # 打开网页
    self.driver.get(response.url)

    # 选择下拉列表中的某个选项
    select = self.driver.find_element_by_xpath('//select[@id="my_select"]')
    select.send_keys("Option 1")
    select.send_keys(Keys.RETURN)

    # 等待数据加载完成
    WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//table[@class="my_table"]')))

    # 提取数据
    data = self.driver.find_elements_by_xpath('//table[@class="my_table"]//tr')

    # 处理数据
    for row in data:
        # 提取数据并进行处理
        pass

    # 选择下拉列表中的另一个选项
    select = self.driver.find_element_by_xpath('//select[@id="my_select"]')
    select.send_keys("Option 2")
    select.send_keys(Keys.RETURN)

    # 等待数据加载完成
    WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//table[@class="my_table"]')))

    # 提取数据
    data = self.driver.find_elements_by_xpath('//table[@class="my_table"]//tr')

    # 处理数据
    for row in data:
        # 提取数据并进行处理
        pass

def closed(self, reason):
    # 关闭 webdriver
    self.driver.quit()

在 Spider 中,我们首先实例化了 Chrome webdriver,并在 parse 方法中使用它来选择下拉列表中的选项,并等待数据加载完成后提取数据。最后,在 closed 方法中关闭 webdriver。

需要注意的是,在使用 Selenium 的 webdriver 时,由于它会在后台启动一个浏览器实例,因此相较于不使用 Selenium 的情况下,爬取速度会稍微慢一些。此外,由于 Selenium 是通过模拟浏览器操作来爬取数据,因此它的稳定性和可靠性可能会受到网页结构和浏览器的影响。

除了使用 Selenium,还有一些其他的方法可以实现类似的效果。例如,有些网页会提供一个 API 接口,我们可以直接通过发送 HTTP 请求来获取数据。另外,有些网页的数据是动态加载的,我们可以使用浏览器的开发者工具来分析网页的数据请求,并直接发送这些请求来获取数据。

总之,在爬取需要下拉列表选择数据的网页时,使用 Selenium 是一种比较常用的方法。我们需要通过模拟浏览器操作来选择不同的下拉列表选项,并通过等待数据加载完成后提取数据。需要注意的是,在使用 Selenium 时,我们需要合理地配置浏览器选项,以达到最优的爬取效果。

@sxfmol
Copy link
Author

sxfmol commented Mar 28, 2023

使用scrapy爬取财经网站的财报数据,涉及到年报、财报等下拉列表选项,这种如何爬取?
使用 Scrapy 爬取财经网站的财报数据,需要模拟网站的下拉列表选项,可以使用 Scrapy 框架自带的 Selectors 和 FormRequest 模块来实现。

以下是一个大致的爬取流程:

定义爬虫的起始页面 URL。
在 spider 的 start_requests() 方法中发起请求。
在回调函数中,使用 response.xpath() 或 response.css() 方法选择页面中需要的元素,并使用 extract() 或 extract_first() 方法将元素提取出来。
根据需要模拟下拉列表选项,生成请求表单数据,并使用 FormRequest() 方法提交表单请求。
在下一个回调函数中处理表单请求的响应,提取需要的数据。
以下是一个简单的示例代码,用于爬取财经网站的财报数据:

python
Copy code

import scrapy

class FinancialStatementSpider(scrapy.Spider):
name = "financial_statement"
start_urls = [
"https://www.example.com/financial_statement"
]
def parse(self, response):
# 提取需要的表单数据,例如财报年份等
formdata = {
'year': '2022',
'report_type': 'annual_report',
}
# 提交表单请求
yield scrapy.FormRequest(url="https://www.example.com/financial_statement",
formdata=formdata,
callback=self.parse_financial_statement)

def parse_financial_statement(self, response):
    # 提取财报数据
    financial_statement = response.xpath('//table[@class="financial-statement-table"]/tbody/tr')
    for row in financial_statement:
        # 解析表格行并提取需要的数据
        financial_data = {
            'date': row.xpath('./td[1]/text()').extract_first(),
            'revenue': row.xpath('./td[2]/text()').extract_first(),
            'profit': row.xpath('./td[3]/text()').extract_first(),
            # ...
        }
        yield financial_data

注意:实际爬取中需要根据网站的具体情况进行调整。涉及到表单提交的爬虫需要仔细分析表单数据,并注意请求头和 cookies 等信息的设置。同时,也需要注意网站的反爬虫策略,例如使用随机的 User-Agent 和代理 IP 等方式进行反爬虫。

@sxfmol
Copy link
Author

sxfmol commented Mar 28, 2023

如果爬取的页面涉及到翻页按钮,可以使用 Scrapy 中的 LinkExtractor 和 scrapy.Request 模块来实现自动翻页的功能。

以下是一个示例代码,用于爬取财经网站的财报数据并翻页:

import scrapy
from scrapy.linkextractors import LinkExtractor

class FinancialStatementSpider(scrapy.Spider):
name = "financial_statement"
start_urls = [
"https://www.example.com/financial_statement?page=1"
]
# 定义 LinkExtractor,用于提取下一页的 URL
page_extractor = LinkExtractor(restrict_xpaths='//ul[@Class="pagination"]/li[last()]/a')

def parse(self, response):
    # 提取财报数据
    financial_statement = response.xpath('//table[@class="financial-statement-table"]/tbody/tr')
    for row in financial_statement:
        financial_data = {
            'date': row.xpath('./td[1]/text()').extract_first(),
            'revenue': row.xpath('./td[2]/text()').extract_first(),
            'profit': row.xpath('./td[3]/text()').extract_first(),
            # ...
        }
        yield financial_data
    # 提取下一页的 URL 并请求
    for link in self.page_extractor.extract_links(response):
        yield scrapy.Request(url=link.url, callback=self.parse)

@sxfmol
Copy link
Author

sxfmol commented Mar 28, 2023

关于403问题的解决,DEBUG: Crawled (403) ?
当 Scrapy 爬取财经网站 API 报错 DEBUG: Crawled (403) 时,很可能是因为网站对爬虫进行了反爬虫处理。这种情况下,可以尝试以下方法:

添加 User-Agent:在请求头中添加一个浏览器的 User-Agent,以模拟浏览器发起的请求,例如:
python
Copy code
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
response = scrapy.Request(url=url, headers=headers)
添加 Referer:在请求头中添加一个合理的 Referer,以表示请求来源,例如:
python
Copy code
headers = {
'Referer': 'https://www.example.com/',
}
response = scrapy.Request(url=url, headers=headers)
使用代理 IP:使用代理 IP 避免被网站识别为爬虫,例如:
python
Copy code
proxies = {
'http': 'http://127.0.0.1:1080',
'https': 'https://127.0.0.1:1080'
}
response = scrapy.Request(url=url, proxies=proxies)
使用 Scrapy 中的 AutoThrottle:Scrapy 中的 AutoThrottle 功能可以自动控制爬虫请求频率,减缓请求速度,以减少被反爬虫机制识别的风险。在 Scrapy 的 settings.py 中开启 AutoThrottle 功能,例如:
python
Copy code
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 5.0
AUTOTHROTTLE_MAX_DELAY = 60.0
如果上述方法无法解决问题,可能需要进一步分析网站的反爬虫机制,例如网站是否通过验证码、IP 封锁等方式进行反爬虫处理,以寻求更具体的解决方案。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment