python爬虫(一)爬取糗事百科

本文介绍了使用Python爬取糗事百科网站数据的过程,对比了正则表达式和BeautifulSoup两种方法,解决了复杂正则表达式导致的问题。

最近需要收集语料,因此学习了一些爬虫的知识,参考网上对糗事百科的爬虫,编写了如下代码

#!usr/bin/env python
# -*- coding: utf-8 -*-

import re
from urllib import request

for page in range(1, 2):
    print(page)
    url = 'http://www.qiushibaike.com/hot/page/' + str(page)
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = {'User-Agent': user_agent}
    try:
        req = request.Request(url, headers=headers)
        with request.urlopen(req, timeout=5) as response:
            content = response.read().decode('utf-8')
            print(content)
            pattern = re.compile(
                '<div class="article block untagged mb15.*?id=(.*?)>.*?<div.*?<a.*?<img.*?<a.*?<h2>(.*?)</h2>'\
                '.*?<a.*?<div.*?<span>(.*?)</span>.*?<!-- 图片或gif -->.*?<div(.*?)<span.*?number">(.*?)</i>'\
                '.*?<i class="number">(.*?)</i>',
                re.S)
            items = re.findall(pattern, content)
            for item in items:
                if not re.search("thumb", item[3]):
                    print(item[0].replace("'", ""), item[1].strip(), item[2].strip(), item[4], item[5])
    except request.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)

对下面正则表达式的解释(引用http://cuiqingcai.com/990.html)

pattern = re.compile(
                '<div class="article block untagged mb15.*?id=(.*?)>.*?<div.*?<a.*?<img.*?<a.*?<h2>(.*?)</h2>'\
                '.*?<a.*?<div.*?<span>(.*?)</span>.*?<!-- 图片或gif -->.*?<div(.*?)<span.*?number">(.*?)</i>'\
                '.*?<i class="number">(.*?)</i>',
                re.S)

1).*? 是一个固定的搭配,.和*代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .*? 的搭配。

2)(.*?)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(.*?)所指代的内容,item[1]就代表第二个(.*?)所指代的内容,以此类推。

3)re.S 标志代表在匹配时为点任意匹配模式,点 . 也可以代表换行符。


以上代码在运行的过程中可能会存在问题(爬着爬着,就跑不动了),查找了一些资料后,给的原因是对于太过复杂的正则表达式,匹配时会出现这样的情况。

鉴于以上这种原因,我们采用BeautifulSoup可以解决,BeautifulSoup是根据html的格式来解析的。具体代码如下

#!usr/bin/env python
# -*- coding: utf-8 -*-

import re
from urllib import request
from bs4 import BeautifulSoup


def find_all(item, attr, c):
    return item.find_all(attr, attrs={'class': c}, limit=1)

for page in range(1, 20):
    print(page)
    url = 'http://www.qiushibaike.com/hot/page/' + str(page)
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = {'User-Agent': user_agent}
    try:
        req = request.Request(url, headers=headers)
        with request.urlopen(req, timeout=5) as response:
            content = response.read().decode('utf-8')
            soup = BeautifulSoup(content, 'html.parser')
            all_div = soup.find_all('div', attrs={'class': re.compile('article block untagged mb15 .*?')})
            for i, e_div in enumerate(all_div):
                result = {}
                result['id'] = e_div.attrs['id']
                result['name'] = e_div.h2.string.strip()
                cont = e_div.find_all('div', attrs={'class': 'content'})
                result['content'] = cont[0].text.strip()
                silme_comment = e_div.find_all('i', attrs={'class': 'number'})
                result['silme_num'] = int(silme_comment[0].text.strip())
                result['comment_num'] = int(silme_comment[1].text.strip())
                print(result)
    except request.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值