编写爬虫的一些感想(就是高兴)

380 查看

今天,根据网页的结构,尝试了下如何抓取煎蛋首页上的文章。目标很简单:

  • 根据首页上面的文章链接,载入文章,而后将文章的标题和正文(不带图片)抓取下来。

  • 抓取首页上面文章的链接,标题,作者和所属标签。

  • 按标题将文章写入一个.txt格式的文件

  • 将首页上抓取的内容整合起来,制作成格式如下的Markdown简介。

首页的简介格式如下:

**文章标题**:鲸鱼有鲸语,鲸语有口音

**文章链接**:[http://jandan.net/2016/02/18/caribbean-whales.html](http://jandan.net/2016/02/18/caribbean-whales.html)

**译者**:Cedric

**标签**:走进科学

...

如此反复即可。这里要说明下,由于煎蛋首页和余下页码的网页结构不同,我没有再写余下页面的简介。如果有人有兴趣的话,可以编写则个~下面,我会说明在编写爬虫过程中的所思所想。

1. 爬虫前的准备

我这里使用了Python中的以下模块:

  • beautifulsoup:第三方模块,用于解析网页内容。

  • requests:第三方模块,用于获取网页内容。

  • re:内置模块,用于编写正则表达式

  • codecs:内置模块,用于操作文件

这便是全部准备了。在这里要多嘴一句,包括re模块在内都存在替代品,如果需要可以根据自己的喜好来选择。

2. 分析程序逻辑

在编写代码之前,要分析如何抓取并处理网页。以抓取一篇文章鲸鱼有鲸语,鲸语有口音为例。我们要实现:

  • 下载网页,获取数据——源代码或者json数据

  • 解析数据,从数据中抽出我们需要的内容——这里是文章标题和文章内容(只有文字)

  • 整理数据,将解析好的数据写入文件中。

这样,可以根据实现的内容,将代码分为三个部分,用函数来整合:

  • download_page(url):接受一个URL(通常是网址),下载网页,而后获取数据(当然,不止下载网页而已,还有很多内容,但对于现在来说,这么讲就好)

  • parse_article(data):接受上面的函数返回的data,并解析为我们需要的内容

  • write_article(title, content):接受上面的函数返回的标题和文章内容,并写入文件中。

这三个部分中,现在我感觉最难的是其中的parse_article(data)。当然,一部分是因为我的经验不足,经常要花很长时间才找到需要的内容。这里,推荐读者在浏览器中使用右键——查找元素来辅助解析网页。

当明白怎么爬取一篇文章的时候,爬取其他内容就是一些细节上的事情了。细节上的内容可以通过模块的文档来获取。我提到的两个第三方模块的中文资料都比较丰富(百度一下即可),所以不再赘述。这里只说明几个需要注意下的细节:

  1. 在发送请求的时候,网页可能会通过检查头信息中的User-Agent来判断是否是一个人浏览网页。最简单的解决问题的方法就是自己写一个头信息,伪装成一个人。

  2. 如果抓取的频率过快,可能会被服务器拒绝访问,如果IP被封了就完了。这里有两个解决问题的思路:

    • 使用IP代理,轮换IP访问网页

    • 设置一个简单的爬虫测试服务器可以接受的访问频率,从慢而快的访问网页。(就是看服务器的忍受程度是多少)

  3. 网页上通常不止有一个地方包含了我们所需的内容(比如有两个块可以实现下一页的功能),所以,一个块难解析可以使用另一个块,变通下嘛~

3. 爬虫实例

这里以抓取一篇文章鲸鱼有鲸语,鲸语有口音为例。刚才提到了,要实现三个函数:

  • download_page(url)

  • parse_article(data)

  • write_article(title, content)

3.1 下载数据

首先是第一个函数download_page(url)。由于内容单一,所以实现比较简单(要注意的是,这里需要准备一些防反爬虫的措施)。下面将展示如何伪装成一个浏览器下载网页或者其中的数据:

def download_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) '
                      'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36'
    }
    data = requests.get(url, headers=headers).content
    return data
    

我们这里伪装了一个火狐浏览器。这个信息不需要你输入或者从这里复制,如果需要的话,可以在浏览器中右键——查看元素——网络而后就可以查看消息头并伪装成你自己的浏览器了。我们这里使用的HTTP请求中的get方法,如果有看过之前的内容(指HTTP权威指南的一部分),就可以明白这里是什么意思啦~

3.2 解析数据

下面是第二个函数parse_article(data),内容比较复杂,而且是根据我们要爬取的文章页面制定的。我们首先放到文章的主体上,右键——查看元素,可以看到主体的部分结构是这样的:

嗯,可以明白(如果不明白的话,请自己补习HTML的基础知识。这部分在Segmantfault里面搜集即可)文章的主体部分在<div class="post f">中。其中,标题在其中的<h1>标签的文本内部,而正文则是其中的<p>标签的内容。

据此,我们可以使用beatifulsoup来实现我们的第二个函数:

def parse_article(html):
    soup = BeautifulSoup(html, 'html.parser')
    # 从上面的数据获取html文档并解析,这里使用的是Python自带的HTML解释器
    article = soup.find('div', attrs={'class': 'post f'})
    # 缩小HTML文档的解析范围,限定在文章主体内部。
    title = article.find('h1').getText()
    # 获取文章主体内部的<h1>标签内的文本,可以发现这就是标题内容。

    paras = []
    # 创建一个列表,以段落的形式,向里面填充文本。

    for paragraph in article.find_all('p'):
        p_content = paragraph.getText()
        # 获取<p>标签内的文本,这里就是段落文本内容。
        paras.append(p_content)

    return title, paras
    # 返回标题和参数,用于写入文件。

3.3 整理数据

获取我们需要的所有数据(标题和内容)以后,需要将其写入文件中。我们首先需要拼接一个文件名,创建并打开文件。这里要注意参数wb。在Python3.X中,b参数是自动添加的(如果没有写则会填上去,有的话就不会自己填上去);但是在Python2.X中不是这样,所以最好填上去,避免换了版本以后出现一些奇怪的Bug。当然,不换也行~

def get_article(title, url):
    file_name = title + '.txt'
    # 拼接文件名
    with codecs.open(file_name, 'wb', encoding='utf-8') as fp:
        html = download_page(url)
        # 调用第一个函数获取数据
        title2, text = parse_article(html)
        # 调用第二个函数获取数据
        fp.write('\t%s\t\r\n' % title2)
        for p in text:
            fp.write('\t%s\r\n' % p)
        # 将获取的数据写入文件。
        
    print('文章读取完毕!')
    return 'OK'

最后,还要再编写一个if语句,判断是运行还是导入。运行文件的时候,可以通过调用第三个函数来实现我们的目的。

if __name__ == '__main__':
    url = 'http://jandan.net/2016/02/18/caribbean-whales.html'
    get_article(url)

4. 文章结束前的一些话

嗯,本文到这里就结束了。下面还有抓取简单首页文章的爬虫。不过爬取的过程也是上面的几步,如果看懂的话,就可以编写出来。看不懂的话……嗯,其实我只是因为开心想炫耀一下,哈哈哈哈来打我啊~~


我是胡一波,集帅气与智慧于一身的美男子,每天都被自己帅醒。如果各位发现这些代码有问题的话,请跟我说,我会尽快回复并发送一块钱!这些钱可以指定给任意人或者机构(比如慈善组织和开源项目),就酱~