HNScraper
HNScraper 是一个用于 HackerNews 的爬虫库,由 Swift 编写。它允许您直接从网站上获取所有文章、评论和用户信息。它还支持登录并进行投票/收藏帖子或评论。
此库类似于 LibHN 库。实际上,该项目的某些部分,如帖子、评论和用户模型以及解析规则,基本上是将 LibHN 库的 Swift 代码转换。
在进一步了解之前,请注意存在一个 官方 API,该 API 实现了基本功能,例如抓取最新、热门和最佳文章、用户信息和评论。但是,它不支持登录和任何相关功能,并且受到许多限制。如果您需要的话,我建议您使用官方 API 而不是这个爬虫。
目录
安装
Pod
确保你的 Podfile
中至少包含以下代码
use_frameworks!
target 'YourAppName' do
pod 'HNScraper', '~> 0.2.1'
end
在你的项目文件夹中运行 pod install
。
然后只需在任何需要爬虫的位置添加 import HNScraper
。
手动
只需将 HNScraper
文件夹中的所有 .swift
文件添加到你的项目中。
文档
完成处理程序 & 错误手势
以下所有操作都是以相同的方式进行:你通过在实例上调用所需参数的方法,并使用完成处理程序来返回你的请求的结果,最后,可能会产生错误。
func getSomething(dependingOn: , completion: ((results?, error?) -> Void))
可能的错误由 HNScrapperError
和 HNLoginError
定义。这些结构通过将最常见错误分类到不同的、具有自我解释的错误类型中来简化错误处理。这种抽象允许你处理常见问题,例如无互联网连接、错误的凭据、不存在的帖子 ID 等,而无需担心“低级”错误,如 URLErrors 和 JSON 错误。
获取帖子列表
帖子列表是 HN 中定义的任何在 HNScraper.PostListPageName
中定义的 HN 页面。
news
front
new
jobs
asks
shows
newshows
active
best
noob
要删除其中之一的30篇第一篇帖子,您必须使用getPostsList
(来自HNScraper
),这将为您返回一个包含HNPost
对象的数组以及下一页的链接,您可以使用该链接获取接下来的30条项目。
typealias PostListDownloadCompletionHandler = (([HNPost], String?, HNScrapperError?) -> Void)
func getPostsList(page: PostListPageName, completion: PostListDownloadCompletionHandler)
例如:
HNScraper.shared.getPostsList(page: .news) { (posts, linkForMore, error) in
// Don't forget to handle the eventual error
for post in posts {
print(post.title)
}
// You also may want to save the linkForMore somewhere.
}
对于30条以上的项目,您必须使用getMoreItems
,并传入您从前30条项目中获得的“更多链接”。这也会返回一个包含HNPost
对象的列表和下一页的链接
func getMoreItems(linkForMore: String, completionHandler: PostListDownloadCompletionHandler)
例如:
HNScraper.shared.getMoreItems(linkForMore: "s") { (posts, linkForMore, error) in
// do whatever you want with the stories
}
获取关于帖子的评论
评论是从一个讨论线程(位于news.ycombinator.com/item?id=
<post_id>
)中解析出来的。您可以通过两种方式获取这些评论:要么是通过
func getComments(ByPostId postId: String, buildHierarchy: Bool = true, completion: @escaping ((HNPost?, [HNComment], HNScraperError?) -> Void))
要么是通过
func getComments(ForPost post: HNPost, buildHierarchy: Bool = true, completion: @escaping ((HNPost, [HNComment], HNScraperError?) -> Void))
参数buildHierarchy
指明评论是否需要以嵌套格式(这意味着结果数组中只有根评论,并指向它们的回复)或线状(平面)格式返回。
使用ByPostId
方法时,将解析帖子的数据以构建一个传递给完成闭包的HNPost
对象。
使用ForPost
方法时,传递给完成闭包的HNPost
实例与您传递给getComments
方法的相同帖子(未修改)。
对于askHN
类型的帖子,第一条评论是OP(原始发帖者)的问题本身。
至于job
类型的帖子,应该没有评论。
获取用户信息
您可以通过调用getUser
方法并传入用户的用户名来获取任何用户的karma、描述和年龄。
func getUserFrom(Username username: String, completion: ((HNUser?, HNScraperError?) -> Void)?)
获取用户的投稿、评论和收藏
请根据您想要抓取的列表使用以下方法(来自HNScraper
)。
func getFavorites(ForUserWithUsername username: String, completion: @escaping PostListDownloadCompletionHandler)
func getSubmissions(ForUserWithUsername username: String, completion: PostListDownloadCompletionHandler)
与前面描述的帖子列表类似,完成闭包将给出一“更多链接”,您可以使用该链接获取更多项目(当然是在需要抓取的项目超过30条时)。
登录 / 登出
这些操作通过单例类HNLogin
来处理。
您可以使用以下方式登录:
func login(username: String, psw: String, completion: @escaping ((HNUser?, HTTPCookie?, HNLoginError?) -> Void))
一旦用户登录,HNLogin
类就会负责存储会话cookie并使其对其他类可用。此外,保存此cookie后,抓取器通过任何请求从网站获取的html将看起来好像用户已经登录。这意味着它将包含所有支持投票(以及最终可能取消支持,如果用户有超过500积分)链接、收藏链接、评论链接等。
HNLogin
类附带其自己的错误枚举HNLoginError
,其中包含badCredentials
情况。在凭证错误的情况下,作为错误返回。
示例
HNLogin.shared.login(username: "username", psw: "pass") { (user, cookie, error) in
if let connected_user = user {
print("logged in user: " + connected_user.username)
} else {
// Handle error
if error == .badCredentials {
print("wrong creds")
} else {
// Check other types of error
}
}
}
您可以通过以下方式登出用户:
func logout()
此方法只是删除存储的会话cookie,使得从HN网站获取的html看起来就像是对未注册的访客一样。
对帖子/评论上下文取消投票
只需使用以下方法之一:
func upvote(Comment comment: HNComment, completion: ((HNScraperError?) -> Void))
func upvote(Post post: HNPost, completion: ((HNScraperError?) -> Void))
func unvote(Post post: HNPost, completion: ((HNScraperError?) -> Void))
func unvote(Comment comment: HNComment, completion: ((HNScraperError?) -> Void))
用户显然需要登录才能执行此操作。否则,将错误.notLoggedIn
传递给完成闭包。
如果完成闭包的error
参数为nil
,则操作成功。否则存在问题。
注意:如果请求的最终状态是预定的最终状态,则认为操作是成功的。因此,如果您尝试取消对未被支持的帖子的投票,则不会有错误。同样,如果您尝试对已支持的条目进行投票,也会没有错误。
(取消)收藏帖子
使用
func favorite(Post post: HNPost, completion: ((HNScraperError?) -> Void))
func unfavorite(Post post: HNPost, completion: ((HNScraperError?) -> Void))
这些方法与对条目进行投票的方法类似。
再次强调,用户需要登录才能进行此操作。否则,将.notLoggedIn
类型的错误传递给完成闭包。
项目结构
模型
爬虫使用3个模型
HNPost
HNComment
HNUser
端点
您将使用两个单例类来执行请求基本有2个单例类
HNScraper
HNLogin
解析配置文件
hn.json
包含了解析每页HN所需的大部分信息。它被引入到LibHN中
尽管其中一些内容发生了变化/已添加,但其结构在LibHN中是相同的。以下部分是原版LibHN文档的更新。
此文件将由单例类 HNParseConfig
下载并存储。
测试
HNScraperTests
文件夹中大多数方法的测试
贡献
欢迎任何形式的贡献。
如果您发现错误,想到改进方案,有建议或者只是想提交一个问题或直接提交一个PR。
此外,我不是英语母语者,所以请不要犹豫,纠正我的一些句子 :)
待办事项
- 完成hn.json配置文件,包含解析所需的其他硬编码字符串
- 提交故事
- 发表评论
- 反对
- 编辑账户(关于、选项、邮件等)
- 搜索
- 测试mac os应用程序
许可证
HNScraper遵循标准MIT许可证。
版权所有© 2017-2018 由Stéphane Sercu所有
特此许可,免费向任何获得本软件及其相关文档副本(“软件”)的个人授予,在不受限制的情况下处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许将软件提供给他人,以便他们可以这样做,但前提是
上述版权声明和本许可通知应包含在软件的所有副本或实质性部分中。
软件按“原样”提供,不提供任何形式的保证,明示或暗示,包括但不限于对适销性、针对特定目的的使用和未经授权的保证。在任何情况下,作者或版权所有者不对任何索赔、损害或其他责任负责,无论是在合同行为、侵权行为或其他行为中产生的,包括但不限于软件或其使用或其他处理的索赔。