背景:在做Python定向图片爬虫时,会通过raw_input输入关键词如“主播”,会爬取标题title中包含"主播"的URL,再去到具体的页面爬取图集。
问题:如果是自定义字符串直接通过: s=u'主播' 定义为Unicode编码,再与同样为Unicode编码的title.text(下一篇文章详细介绍该爬虫)比较即可。但是如果需要raw_input输入呢?而且在通过unicode或decode转换过程中总是报错,为什么呢?
主要问题是如何将str转换为unicode编码(How to convert str to unicode),默认python编码方式ascii码。
unicode(string[, encoding[, errors]])
>>> help(unicode)
Help on class unicode in module __builtin__:
class unicode(basestring)
| unicode(object='') -> unicode object
| unicode(string[, encoding[, errors]]) -> unicode object
|
| Create a new Unicode object from the given encoded string.
| encoding defaults to the current default string encoding.
| errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.
举个简单的例子:需要判断搜索词key是否在title标题中。# coding=utf-8
import sys
def getTitle(key,url):
#title = driver.find_element_by_xpath()
title = u'著名女主播Miss与杰伦直播LOL'
print key,type(key)
print title,type(title)
if key in title:
print 'YES'
else:
print 'NO'
key = raw_input("Please input a key: ")
print key,type(key)
url = 'http://www.baidu.com/'
getTitle(key,url)
输出如下图所示:
s = '主播'
s.decode('utf-8').encode('gb18030')
最后解决方法从stackoverflow得到,一方面说明自己确实研究得不是很深,另一方面那个论坛确实更强大。参考:
此时你的爬虫仅仅是能从raw_input中输入进行处理或者定义unicode的字符串进行定向爬取,但是如果关键词很多就需要通过读取文件来实现。如下图所示,是我"Python爬取百度InfoBox"这篇文章。同样,你会遇到各种中文乱码问题需要处理。
举个简单例子:通过Selenium爬取百度百科Summary第一段。
# coding=utf-8
import sys
import os
import urllib
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import selenium.webdriver.support.ui as ui
from selenium.webdriver.common.action_chains import ActionChains
#driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")
driver = webdriver.Firefox()
wait = ui.WebDriverWait(driver,10)
def getTitle(line,info):
print 'Fun: ' + line,type(line)
driver.get("http://baike.baidu.com/")
elem_inp = driver.find_element_by_xpath("//form[@id='searchForm']/input")
elem_inp.send_keys(line)
elem_inp.send_keys(Keys.RETURN)
elem_value = driver.find_element_by_xpath("//div[@class='lemma-summary']/div[1]").text
print 'Summary ',type(elem_value)
print elem_value,'\n'
info.write(line.encode('utf-8')+'\n'+elem_value.encode('utf-8')+'\n')
time.sleep(5)
def main():
source = open("E:\\Baidu.txt",'r')
info = open("E:\\BaiduSpider.txt",'w')
for line in source:
line = line.rstrip('\n')
print 'Main: ' + line,type(line)
line = unicode(line,"utf-8")
getTitle(line,info)
else:
info.close()
main()
其中TXT通常默认为ANSI编码,代码步骤:import codecs
#用codecs提供的open方法来指定打开的文件的语言编码,它会在读取的时候自动转换为内部unicode
info = codecs.open(baiduFile,'w','utf-8')
#该方法不是io故换行是'\r\n'
info.writelines(key.text+":"+elem_dic[key].text+'\r\n')
PS: 该部分主要参考书籍《Python核心编程(第二版)》作者Wesley J.Chun
什么是Unicode
Unicode字符串声明通过字母"u",它用来将标准字符串或者是包含Unicode字符的字符串转换成完全的Unicode字符串对象。Python1.6起引进Unicode字符串支持,是用来在多种双字节字符的格式、编码进行转换的。
Unicode是计算机支持这个星球上多种语言的秘密武器。在Unicode之前,用的都是ASCII码,每个英文字符都是以7位二进制数的方式存储在计算机内,其范围是32~126。当用户在文件中键入A时,计算机会把A的ASCII码值65写入磁盘,然后当计算机读取该文件时,它会首先把65转换成字符A再显示到屏幕上。
但是它的缺点也很明显:对于成千上万的字符来说,ASCII实在太少。而Unicode通过使用一个或多个字节来表示一个字符的方法,可以表示超过90,000个字符。
>>> s1 = "中文"
>>> s1
'\xd6\xd0\xce\xc4'
>>> print s1,type(s1)
中文
>>> s2 = u"中文"
>>> s2
u'\xd6\xd0\xce\xc4'
>>> print s2,type(s2)
ÖÐÎÄ
>>>
前面添加'u'声明为Unicode字符串,但它实际的编码并没有改变。>>> s = '中文'
>>> s
'\xd6\xd0\xce\xc4'
>>> print s,type(s)
中文
>>> s.decode('gb2312')
u'\u4e2d\u6587'
>>> print s.decode('gb2312'),type(s.decode('gb2312'))
中文
>>> len(s)
4
>>> len(s.decode('gb2312'))
2
>>> t = u'中文'
>>> t
u'\xd6\xd0\xce\xc4'
>>> len(t)
4
>>> print t,type(t)
ÖÐÎÄ
>>>
前缀'u'表示字符串是一个Unicode串,仅仅是一个声明。
源自:http://xianglong.me/article/learn-python-1-chinese-encoding/
结合我遇到的两个问题,归纳了以下几点。常见中文编码问题解决方法包括:
1.遵循PEP0263原则,声明编码格式
在PEP 0263--Defining Python Source Code Encodings中提出了对Python编码问题的最基本的解决方法:在Python源码文件中声明编码格式,最常见的声明方式:
#!/usr/bin/python
# -*- coding: -*-
根据这个声明,Python会尝试将文件中的字符编码转为encoding编码,它可以是任意一种Python支持的格式,一般都会使用utf-8\gbk的编码格式。并且它尽可能的将指定地编码直接写成Unicode文本。 str1 = '中文'
str2 = u'中文'
Python中有以上两种声明字符串变量的方式,它们的主要区别是编码格式的不同,其中tr1的编码格式和Python文件声明的编码格式一致,而str2的编码格式则是Unicode。#设置编码utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
#显示当前默认编码方式
print sys.getdefaultencoding()
这种方法是可以解决部分编码问题,但是同时也会引入很多其他问题,得不偿失,不建议使用这种方式。总结
最后希望文章对你有所帮助,尤其是你刚好遇到这个问题的,由于是结合最近做的东西,所以文章比较杂乱,但如果你刚好需要,确实能解决你的问题的。
纪伯伦曾说过:“你无法同时拥有青春和关于青春的知识;因为青春忙于生计,没有余暇去求知;而知识忙于寻求自我,无法享受生活。”
同样现在找工作的我,无法在拥有扎实基础知识的同时又兼顾深度的项目理解,但我更倾向于分享知识,因为它就是寻求自我,就是享受生活,就是编程之乐~