<commit_before># 第一周开发报告
## 本周已完成

- 完成新闻网站调查工作的划分, 这部分工作将持续进行。
- 已完成简单的需求设计, 即完成一个用来抓取新闻网站的后台工具
- 详细计划正在筹划当中

调查工作的划分:

![](week1_works.png)

### 另:计划外

原先已经完成了一部分的爬虫工作, 但目前部署在负责人的个人工程文件里面, 等需求确定下来之后, 再部署到该repo。<br />
爬虫功能的架构, 实际上不受需求变化的影响, 故在此介绍一下:

### `NoticeFetcher`

抽象类`NoticeService`的结构, 采用组件化的方式, 即scala中的mixin模式, 代码形式上, 继承了`UrlService`, `IndexService`, `NoticeFetcher`这三个特质(trait, 类似于Java 8中带默认实现的接口), 代码如下

```scala
abstract class NoticeService(val source: String) extends UrlService with IndexService with NoticeFetcher {
  def getUrls: Iterable[NoticeEntry] =
    indexUrls.map(u ⇒ Try(noticeUrlsFromUrl(u))).takeWhile(_.isSuccess).flatMap(_.get) //注意indexUrls和noticeUrlsFromUrl方法未实现
  def notices(after: Date = new Date(0)): Iterable[Notice] = getUrls.map(n ⇒
    Try(fetch(n))).filter(_.isSuccess).map(_.get).takeWhile(_.date.after(after)) //注意fetch方法未实现
}
```

NoticeService需要用到继承的三个特质的方法(代码注释已标出), 其中(scala中默认可见范围为public), `UrlService`提供`noticeUrlsFromUrl(String): Iterable[NoticeEntry]`方法, 通过给定的索引链接返回新闻标题和链接(封装在`NoticeEntry`)的序列, `IndexService`提供`indexUrls: Iterable[String]`方法, 给出索引链接的序列(一个新闻网站的目录有很多页), `NoticeFetcher`提供`fetch(NoticeEntry): Notice`方法, 通过给定的新闻链接和标题, 提取出新闻(封装成`Notice`), 为了方便起见, 定义了一些protected方法, 在这里可以忽略:

```scala
trait UrlService {
  def noticeUrlsFromUrl(url: String): Iterable[NoticeEntry]
}

trait IndexService {
  protected val template: String
  protected val firstIndex: Int = 1
  protected def valueStream(i: Int): Stream[Int] = i #:: valueStream(i + 1)
  protected def indexNums: Iterable[Any] = valueStream(firstIndex)
  protected def interpolate(value: Any): String = template.replaceAll("<index>", value.toString)
  def indexUrls: Iterable[String] = indexNums map interpolate
}<commit_msg>Update week1.md<commit_after># 第一周开发报告
## 本周已完成

- 完成新闻网站调查工作的划分, 这部分工作将持续进行。
- 已完成简单的需求设计, 即完成一个用来抓取新闻网站的后台工具
- 详细计划正在筹划当中

调查工作的划分:

![](week1_works.png)

### 另:计划外

原先已经完成了一部分的爬虫工作, 但目前部署在负责人的个人工程文件里面, 等需求确定下来之后, 再部署到该repo。<br />
爬虫功能的架构, 实际上不受需求变化的影响, 故在此介绍一下:

### `NoticeFetcher`

抽象类`NoticeService`的结构, 采用mixin模式, 代码形式上, 继承了`UrlService`, `IndexService`, `NoticeFetcher`这三个特质(trait, 类似于Java 8中带默认实现的接口), 代码如下

```scala
abstract class NoticeService(val source: String) extends UrlService with IndexService with NoticeFetcher {
  def getUrls: Iterable[NoticeEntry] =
    indexUrls.map(u ⇒ Try(noticeUrlsFromUrl(u))).takeWhile(_.isSuccess).flatMap(_.get) //注意indexUrls和noticeUrlsFromUrl方法未实现
  def notices(after: Date = new Date(0)): Iterable[Notice] = getUrls.map(n ⇒
    Try(fetch(n))).filter(_.isSuccess).map(_.get).takeWhile(_.date.after(after)) //注意fetch方法未实现
}
```

NoticeService需要用到继承的三个特质的方法(代码注释已标出)
其中(scala中默认可见范围为public):
- `UrlService`提供`noticeUrlsFromUrl(String): Iterable[NoticeEntry]`方法,<br />通过给定的索引链接返回新闻标题和链接(封装在`NoticeEntry`)的序列
- `IndexService`提供`indexUrls: Iterable[String]`方法,<br />给出索引链接的序列(一个新闻网站的目录有很多页)
- `NoticeFetcher`提供`fetch(NoticeEntry): Notice`方法,<br />通过给定的新闻链接和标题, 提取出新闻(封装成`Notice`), 为了方便起见, 定义了一些protected方法, 在这里可以忽略:

```scala
trait UrlService {
  def noticeUrlsFromUrl(url: String): Iterable[NoticeEntry]
}

trait IndexService {
  protected val template: String
  protected val firstIndex: Int = 1
  protected def valueStream(i: Int): Stream[Int] = i #:: valueStream(i + 1)
  protected def indexNums: Iterable[Any] = valueStream(firstIndex)
  protected def interpolate(value: Any): String = template.replaceAll("<index>", value.toString)
  def indexUrls: Iterable[String] = indexNums map interpolate
}
{'fraction_non_alphanumeric': 0.13239517518667432, 'fraction_numerical': 0.0031591039632395176, 'mean_word_length': 7.433414043583535, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2793007', 'n_tokens_mistral': 1761, 'n_tokens_neox': 1885, 'n_words': 234}