python爬虫初学(一)——基本代码和常见问题

来源:互联网 发布:乐语软件图标 编辑:程序博客网 时间:2024/06/05 10:54

导语

本文出自一个第一次接触python爬虫的新手,第一次独立写爬虫。所以很多东西都用的最基础的,没有使用成熟的python爬虫框架,只是请求网页,写正则表达式匹配需要信息。希望对新手的你有所帮助。

目标及思路

任务:
爬取国家统计局http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/index.html地理名称信息,包括省市区街道社区乡镇等。
思路:
该网站结构是树形的,即层层递进,想要爬取这里所有的信息,需要深度或广度搜索。这里,我采用了多叉树的层序遍历(不确定list容器是不是会爆掉)
结合目标网站进一步解释:
先获取当前网页根url,并将该url加入list容器。每次弹出一个url,进行相应加工成新的可点击的url,将新url压入list,同时通过正则匹配获取需要信息写入txt文件。重复操作直到list为空,证明所有的url都已经遍历完毕。

关键方法

层序遍历代码:(大致看看即可,因为每个人的目标网址和需要内容都不一样,主要是思想)

def bfsLink(LinkList,headers):    firstUrl = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/'    f = codecs.open(r'f:/localInfo.txt', 'a','utf-8')    while(LinkList):        flag = 1 # 标记当前页面是爬到最低层还是非最低层,最低层的链接长度为17        addurl = LinkList.pop() # 当前页面超链接字符串        if(len(addurl)==7 or len(addurl)==12): # 11.html 11/1101.html            newurl = firstUrl + addurl        if(len(addurl)==14):                   # 01/110101.html            temp=addurl[3:5]            newurl=firstUrl+temp+"/"+addurl        if(len(addurl)==17):                   # 01/110101001.html            temp1=addurl[3:5]            temp2=addurl[5:7]            newurl=firstUrl+temp1+"/"+temp2+"/"+addurl            flag=0        # 非最低层的正则串和最低层正则串有略微不同        if(flag==1):            pattStr=ur'[0-9]{12}</a>.*?<td.*?><a.*?href=\'(.*?)\'>(.*?)</a></td>'        else:            pattStr=ur'[0-9]{3}</td>.*?</td><td>(.*?)</td></tr>'        print newurl        content=getPageContent(newurl,headers=headers)        pattern = re.compile(pattStr)        items = re.findall(pattern, content)        for item in items:            # 若该页面不是最低层,即存在超链接,则将超链接加入list            if flag==1:                str=getLabel(item[1])                print 'label:',str                f.write(item[1] + '@@' + str + '\r\n')                LinkList.append(item[0])                print item[1]            # 若该页面是最低层            else:                str = getLabel(item)                print 'label:', str                f.write(item + '@@' + str + '\r\n')                print item    f.close()

总结


常用代码

  • 字符串保存成txt文件

    content = u'你好,脚本之家 jb51.net'content+='\r\n'content+=u'你好,脚本之家 jb51.net'f = codecs.open('f:/1.txt','w','utf-8') # 重新写入文本,如果是追加,则‘w’改为‘a’即可f.write(content)f.close()
  • 爬虫的基本写法
#  !/usr/bin/python# -*- coding:utf-8 -*- #import urllib2import redef getPageContent(url,headers):    request = urllib2.Request(url, headers=headers)    response = urllib2.urlopen(request)    content = response.read().decode('GB2312').encode('utf-8')    return contenturl='http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/61/6101.html'user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' #  伪装成浏览器的访问headers = {'User-Agent': user_agent}content = getPageContent(url,headers) # 输出网站内容print content  # 正则串要根据爬取内容寻找规律,其中()代表一个分组,第一个括号即item[0],依次类推。 # 若只有一个分组,则直接循环输出item即可patternStr=ur'[0-9]{12}</a>.*?<td.*?><a.*?href=\'(.*?)\'>(.*?)</a></td>' pattern = re.compile(patternStr)result = re.findall(pattern, content)for item in result:    print item[0]    print item[1]

遇到的问题

  • 问题:运行提示[Errno 10060]错误
    原因:爬取页面过快造成暂时被网站禁止
    解决方法一:在请求网页并获取content函数的代码中设置睡眠时间,防止爬取过快。(本来我设置的是睡眠1s,但还是报10060错误,偶然改成2s,只是中断的时间推迟了,还是没有爬完所有数据,最后,改成了睡眠时间是随机的,服务器更小概率地认为请求是非人类操作,竟然成功了)。代码为:

    second=random.uniform(2,5) # 每次生成一个2-5直接的随机浮点数time.sleep(second)

    解决方法二:设置代理。参看博客http://blog.csdn.net/wqy20140101/article/details/78547987 很多博主都说这样可以避免10060错误。
    注:实际问题上,因为我这次爬取的数据实在是太多了,所以我采用了两者方法结合的方式,只设置了一个代理,并且加入了睡眠实际。即便我这样修改,还是总出现502等错误,所以中断的时候,我会人工检查在哪里中断,稍微改动代码接着运行,当然,这是很下策的方法,但是我实在没有找到其他的解决思路。 希望路过的朋友可以指点一二。

  • 问题:报错sre_constants.error: unbalanced parenthesis
    原因:正则表达式括号不匹配,例如:正则串最后一个右括号没有匹配对象

    pattStr=r'<td.*?class=.*?><td>(.*?)</td><td>(.*?)</td>)'

    解决:反复检查修改正则串

  • 问题:报错UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 1: ordinal not in range(128)
    原因:读取文件时使用的编码默认时ascii而不是utf8
    解决:加入以下代码

    import sysreload(sys)sys.setdefaultencoding('utf8')
  • 中文乱码问题
    原因:网站自身有编码,python程序默认有编码,两者编码很有可能是不一致的。若网站输出有中文,可能出现乱码问题
    解决:首先查看网站自身的编码,在网页源码head标签中注明。
    以实验网站为例:

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">

    因此,在读取页面时对网页内容先解码后编码。代码为:

    request = urllib2.Request(url, headers=headers)response = urllib2.urlopen(request)content = response.read().decode('GB2312').encode('utf-8')
阅读全文
1 0
原创粉丝点击