刮削SDK

scraperx的Python项目详细描述


scraperx软件开发工具包

pypi
pypi

入门

  1. 创建scraper将驻留的新目录并添加以下文件:
    • 一个配置文件:config.yaml
    • scraper文件:your_scraper.py(示例)
  2. 下一步从pypi安装这个库:pip install scraperx
  3. 运行python your_scraper.py dispatch运行完整的scraper
    • 要查看命令的参数,请执行以下操作:python your嫒scraper.py dispatch-h
    • 查看所有可用的命令:python your_scraper.py-h

样本刮刀

样本刮削器可在本回购协议的示例文件夹中找到

开发

任何时候刮刀需要覆盖底座时,总是像这样传入*args&;**kwargs参数:

def__init__(self,*args,**kwargs):super().__init__(*args,**kwargs)

调度

任务数据

这是传递给流程每个步骤的值的指令。刮刀可以把它需要的东西放在这里。但以下是一些不需要的内置值,但如果您提供了它们,则会使用它们:

  • :要使用每个请求的头的dict
  • 代理:要使用的完整代理字符串
  • 代理国家:用于获取此区域的代理,如果未设置此和代理,则将使用随机代理。
  • 设备类型:如果未设置用户代理,则在设置用户代理时使用。选项包括桌面移动

正在下载

使用requests.session发出get和post请求。 basedownload类的\u init可以接受以下参数:

  • 任务:必需。调度员的任务
  • headers:(named arg)dict为整个会话设置标题。默认值:设备类型的随机用户代理,如果未设置设备类型,将使用桌面
  • proxy:(named arg)用于请求的代理字符串
  • ignore_codes:(named arg)不重试的http状态代码列表。如果看到这些代码,它会将请求视为任何其他成功的请求。

使用BaseDownloader时,会在self.session下创建一个请求会话,因此您所做的每个get/post都将在每个任务中使用相同的会话。 也可以通过将关键字args赋给self.request_get()self.request_post()来设置每个调用的头。您传递给self.request-get/post的任何Kwargs都将被传递给sessions-get/post方法。

当使用basedownloader的get&post函数时,它将使用在in it中创建的请求会话和pythonrequests响应对象。

请求将重试n次(默认情况下为3次)以获取成功的状态代码,每次重试都将尝试并触发一个名为new_profile()的函数,在该函数中,您有机会切换请求使用的头/代理(仅更新该请求?)。如果该函数不存在,它将使用相同的数据重试。

有一些自定义参数可以传递到这个sdk将使用的self.request.函数中。其他人都会被传给请求方法调用。
命名参数:

  • 最大尝试次数:默认值=3。键入int。将尝试请求的次数,每次尝试都将尝试获取新的代理和用户代理
  • 自定义源检查:默认值=无。键入列表列表。用于将请求设置为基于在页源上运行的正则表达式的设置状态代码。
    • 这将查看单词captcha是否在源页面中,并将响应状态代码设置为403,状态消息为capacha found。状态消息就在那里,这样您就知道它是真正的403还是您的自定义状态。
      • [(重新编译(r'captcha,re.i),403,找到capacha')]

保存源

这是提取器在下载的数据上运行所必需的。在self.download()中,只需对发出的请求调用self.save_request(r)。这将把源文件添加到保存的源列表中,这些源将被传递给提取器进行解析。
一些关键字参数可以传递到self.save_request

  • 模板值{dict}-要在模板中使用的附加键
  • 文件名{str}-从配置中的模板名中覆盖文件名

下载异常

调用self.request.时将引发这些异常。它们会被安全地抓住,所以刮刀不需要抓住它们。但是,如果刮刀想基于异常执行某些操作,则可以在刮刀周围使用try/except命令。

  • scraperx.exceptions.downloadvalueerror:如果有一个异常未被其他异常捕获
  • scraperx.exceptions.httpignorecodeerror:当在basedownload的ignore参数中找到请求的状态代码时
  • requests.exceptions.httperror:当请求返回一个不成功的状态代码并且在忽略代码中找不到时

设置标题/代理

self.request-get/request-post中设置的值将与在初始化中设置的值合并,如果键相同,则覆盖。

self.request-get/request-post-kwargs头/代理
将覆盖
self.task[标题/代理]
将覆盖
初始化Kwargs头/代理

请求上设置的任何头/代理(get/post/etc)将只为该单个请求设置。要在会话中设置这些值,必须从init或任务数据中设置它们。

代理

如果您有一个代理列表,下载程序应该在它们之间自动旋转,那么可以以以下格式保存在csv中:

proxy,country
http://user:pass@some-server.com:5500,US
http://user:pass@some-server.com:5501,US
http://user:pass@some-server.com:6501,DE

将env varproxy_文件设置为上述csv的路径,以便刮刀将其加载。
如果您尚未在任务中直接传入代理,并且此代理csv存在,则它将从此文件中随机抽取一个代理。如果在任务数据中设置了代理国家/地区,它将使用代理国家/地区来选择要代理到的正确国家/地区。

用户代理

如果没有直接设置用户代理,则会根据任务数据中的设备类型拉取一个随机代理。
如果未设置设备类型,则默认使用桌面用户代理。 要设置自己的用户代理列表以供选择,请按以下格式创建CSV:

device_type,user_agent
desktop,"Some User Agent for desktop"
desktop,"Another User Agent for desktop"
mobile,"Now one for mobile"

将env varua_文件设置为上述csv的路径,以便铲运机将其装入。

提取

Parsel文档

数据提取帮助程序

self.查找css元素(源,css选择器)

  • source-解析对象以运行css se选择器打开
  • css\u选择器-尝试提取数据的css选择器列表

从返回数据的第一个css选择器返回parsel元素。

此片段将位于scrapersmyscraperextract(extract)类中,用于提取数据的方法中。

title_selectors=['h3','span.title',]result['title']=self.find_css_elements(element,title_selectors)\
                      .xpath('string()').extract_first().strip()

有一些内置的解析器可以帮助提取某些类型的数据

fromscraperximportparsers#### Price#### This will parse the price out of a string and return the low and high values as floatsraw_p1_str='15,48€'p1=parsers.price(raw_p1_str)# p1 = {'low': 15.48, 'high': None}raw_p2_str='1,999'p2=parsers.price(raw_p2_str)# p2 = {'low': 1999.0, 'high': None}raw_p3_str='$49.95 - $99.99'p3=parsers.price(raw_p3_str)# p3 = {'low': 49.95, 'high': 99.99}#### Rating#### Parse the rating from a string# Examples: https://regex101.com/r/ChmgmF/3raw_r1_str='4.4 out of 5 stars'r1=parsers.rating(raw_r1_str)# r1 = 4.4raw_r2_str='An average of 4.1 star'r2=parsers.rating(raw_r2_str)# r2 = 4.1

如果您希望这些解析器捕获更多的案例,请打开您试图解析的用例的问题。

测试

更新提取器时,可能无法与以前的源文件一起使用。因此,有一个源和它的qa'd数据文件可以用来进行测试,以验证数据仍在正确提取。

创建测试文件
  1. 运行python your_scraper.py create test path_to/metadata_source_文件
    • 输入文件是运行scraper并下载源文件时创建的*_metadata.json文件。
  2. 这将使用下载源(从元数据)的时间作为文件名,将元数据文件和源复制到目录tests/sample_data/your_scraper/中。
    • 它还根据提取器为每个源创建提取的qa文件。
    • 它以json格式提取数据,以便于qa和读取。
  3. 它创建的qa文件将在文件名中提取qa。你要做的就是确认文件中的所有值都是正确的。如果一切看起来都很好,那么请将文件名从提取到提取。这将使系统知道文件已被检查,并且这是它在测试时用来比较的数据。
  4. 创建一个空文件tests/\u init.py。这是运行测试所必需的。
  5. 接下来是创建运行测试的代码。使用下面的内容创建文件tests/tests.py
importunittest# The testingframe work to usefromscraperx.testimportExtractorBaseTest# Does all the heavy lifting for the testfromyour_scraperimportscraperasmy_scraper# The scrapers Scraper class# If you have multiple scrapers, then import their extract classes here as well# This test will loop through all the test files for the scraperclassYourScraper(ExtractorBaseTest.TestCase):def__init__(self,*args,**kwargs):# The directory that the test files for your scraper are indata_dir='tests/sample_data/your_scraper'# ignore_keys will not test the qa values to the current extracted test value. This is most useful when dealing with timestamps or other values that will change on each time the data is extractedsuper().__init__(data_dir,my_scraper,ignore_keys=['time_extracted'],*args,**kwargs)# If you have multiple scrapers, then create a class for each# Feel free to include any other unit tests you may want to run as well
  1. 运行测试python-m unittest discover-vv

配置

设置配置值的3种方法:

  • cli参数:将重写任何其他类型的配置值。使用-h查看可用选项
  • 环境变量:将重写yaml中的配置值
  • yaml file:如果没有为键设置其他方式,则将使用这些值

配置值

# config.yaml# This is a config file with all config values# Required fields are marked as suchdefault:extractor:save_data:service:local# (local, s3) Default: localbucket_name:my-extracted-data# Required if `service` is s3, if local this is not neededfile_template:test_output/{scraper_name}/{id}_extracted.json# Optional, Default is "output/source.html"downloader:save_metadata:true# (true, false) Default: true. If false, a metadata file will NOT be saved with the downloaded source.save_data:service:local# (local, s3) Default: localbucket_name:my-downloaded-data# Required if `service` is s3, if local this is not neededfile_template:test_output/{scraper_name}/{id}_source.html# Optional, Default is "output/extracted.json"dispatch:limit:5# Default None. Max number of tasks to dispatch. If not set, all tasks will runservice:# This is where both the download and extractor services will runname:local# (local, sns) Default: localsns_arn:sns:arn:of:service:to:trigger# Required if `name` is sns, if local this is not neededratelimit:type:qps# (qps, period) Required. `qps`: Queries per second to dispatch the tasks at. `period`: The time in hours to dispatch all of the tasks in.value:1# Required. Can be an int or a float. When using period, value is in hours

如果您使用的是文件模板配置,则python.format()将在此字符串上运行,以便您可以使用{key_name}使其成为动态的。您可以直接访问的键如下:

  • 已分派任务中的所有键
  • 对于.save()fn,传递到模板值{}kwarg中的任何内容
  • 下载的时间:从下载程序(在下载程序和提取程序中)经过的时间(UTC)
  • 下载日期:从下载程序(在下载程序和提取程序中)传递的日期(UTC)
  • 提取的时间:从提取程序(仅在提取程序中)传递的时间(UTC)
  • 提取日期:从提取程序(仅在提取程序中)传递的日期(UTC)

default部分下的任何内容也可以为每个刮刀都有自己的值。因此,如果我们有一个名为"搜索"的刮板,并且希望它使用不同的速率限制,那么您可以执行的所有其他刮板:

# Name of the python filesearch:dispatch:ratelimit:type:periodvalue:5

要使用环境变量覆盖上述代码片段中的值,请设置dispatch_ratelimit_value=1。这将覆盖默认和自定义的所有分派速率限制值。

问题

如果遇到错误,调用fork()时,另一个线程可能正在运行运行scraper时在mac上本地。然后设置env varexport objc_disable_initialize_fork_safety=yes 这是因为在从线程生成线程时,Mac上有一个安全设置:https://github.com/ansible/ansible/issues/32499 issuecomment-341578864" rel="nofollow">https://github.com/ansible/ansible/issues/32499 issuecomment-341578864

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何从数组中打印int值?   prepared语句Java中奇怪的异常PreparedStatement:参数索引超出范围   封装如何在OOP Java中为主方法编码?   java某些手机显示快捷方式徽章需要什么权限?   java TextView不会随OnItemSelectedListener更改   java注释处理器不会自动触发吗?   java Spring JPA如何计算外键数   c#对于这个简单的OOAD问题,哪种设计最优雅?   java如何处理while循环中的异常?   Android Studio错误:进程'command'/home/draven/Downloads/安卓studio/jre/bin/java''结束,退出值为非零2   在使用Payara服务器的Vaadin应用程序中导航到根目录时,java将丢失上下文根目录   使用contentType application/json而不是application/jsonpatch+json的java修补程序   带有tomcat的java HAproxy连接不足   Java:在应用过滤器后创建一个简单的通用方法进行计数   java如何使用多态性创建一个实例化对象的方法,然后用它们高效地填充ArrayList?