爬虫准备
1 装载虚拟环境
pip virtualenv
可以在任意位置创建虚拟环境
virtualenv 文件夹名
如果想指定python版本 -p python3.exe (路径)
2 更新pip
pip -- upgrade
3 获取响应头
response = urllib2.urlopen () 之后
response.info () 获取所有响应头
response
Fiidler
makecert. exe -r -ss my -n "CN=DO_NOT_TRUST_FiddlerRoot, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com" -sky signature -eku 1.3 .6 .1 .5 .5 .7 .3 .1 -h 1 -cy authority -a sha1 -m 120 -b 09 /05 /2012
在cmd里面运行
爬虫爬取
一些知识
1 直接编译,在直接网址输入时引用(可看百度翻译)
from urllib import quote
if __name__ == '__main__' :
key = raw_input('请输入要翻译的内容:' )
key = quote(key)
2 方法编译,网址里面有=号,通过字典编译(可看爬取贴吧)
xq = { 'pn' :key, }
xq = urllib.urlencode(xq)
fullurl = base_url + xq
request = urllib2.Request(fullurl)
response = urllib2.urlopen(request)
3 post和get请求
post
data = urllib.urlencode(data)
requeset = urllib2.Request(base_url,data=data)
get不用
4 正则跨行 (加 re.s)
td_pattern = re.compile(r'<tr.*?</tr>' ,re.S)
常用方法
1
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
2 json转化成字典
json.loads(内容) 通常用于查看json里的内容
print json.dumps(data,indent=4 ,ensure_ascii=False )
基本
爬取一个网页
#coding:utf8
import urllib2
base_url =
request = urllib2.Request (base_url)
response = urllib2.urlopen(request ,timeout=30 )
print response .read()
查询爬取网页
import urllib
import urllib2
def search (key) :
base_url = 'http://www.baidu.com/s?'
qs = {
'wd' :key,
}
qs = urllib.urlencode(qs)
fullurl = base_url + qs
request = urllib2.Request(fullurl)
response = urllib2.urlopen(request)
return response.read()
if __name__ == '__main__' :
key = raw_input('请输入查询关键字:' )
result = search(key)
print result
爬取贴吧第几页到第几页
import urllib
import urllib2
import os
def search (key) :
base_url = 'http://tieba.baidu.com/f?kw=%C3%C0%C5%AE&'
xq = {
'pn' :key,
}
xq = urllib.urlencode(xq)
fullurl = base_url + xq
request = urllib2.Request(fullurl)
response = urllib2.urlopen(request)
return response.read()
if __name__ == '__main__' :
ys = raw_input('请输入要查询的页数:' )
ys1 = ys.split(',' )
print ys1
x1 = int(ys1[0 ])
x2 = int(ys1[1 ])
if x2 >= x1:
while x1 <= x2:
key = (x1-1 )*50
result = search(key)
print ('当前页数' +str(x1))
z2 = result
fp = open('my1.txt' ,'a+' )
fp.write(z2)
fp.close()
x1 += 1
else :
while x2 <= x1:
key = (x2-1 )*50
result = search(key)
print('当前页数' +str(x2))
z1 = result
fp = open('my.txt' ,'a+' )
fp.write(z1)
fp.close()
x2 += 1
百度翻译
import urllib2
import urllib
import json
def translate (key) :
base_url = 'https://fanyi.baidu.com/v2transapi'
data = {
"from" : "en" ,
"to" : "zh" ,
"query" : key,
"simple_means_flag" : "3" ,
}
data = urllib.urlencode(data)
requeset = urllib2.Request(base_url,data=data)
response = urllib2.urlopen(requeset)
data_json = response.read()
data = json.loads(data_json)
res = data['dict_result' ]['simple_means' ]['word_means' ]
for item in res:
print item
if __name__ == '__main__' :
while True :
key = raw_input('输入翻译单词:' )
if key == 'q' :
exit()
else :
translate(key)
自己写的
import urllib
import urllib2
from urllib import quote
def search (key) :
base_url = 'https://fanyi.baidu.com/'
if '%' in key:
key = '#zh/en/'
fullurl = base_url + key
print fullurl
else :
key = '#en/zh/'
fullurl = base_url + key
print fullurl
request = urllib2.Request(fullurl)
response = urllib2.urlopen(request)
return response.read()
if __name__ == '__main__' :
key = raw_input('请输入要翻译的内容:' )
key = quote(key)
print(key)
result = search(key)
print(result)
第一个反爬虫
#coding:utf8
import urllib2
import random
# base_url = 'http://www.baidu.com/'
base_url = 'http://www.xicidaili.com/'
# 构造一个请求
# 构造header
# 爬虫和反爬虫斗争第一点,user-agent
# 反爬虫第一步,防止user-agent ,ip (频繁请求封ip地址),
#
ua_list = [
'User-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 ' ,
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36' ,
'User-Agent:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;' ,
'User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)' ,
]
UserAgent = random.choice(ua_list) # 随机一个浏览器
# print UserAgent
# headers = {
# # 默认User-Agent : python-spider
# # 'User-Agent' : UserAgent,
# }
request = urllib2.Request(url=base_url)
request.add_header('User-Agent' ,UserAgent) #设置一个请求头
print request.get_header('User-agent' ) # 获取一个请求头
response = urllib2.urlopen(request)
print response.read()
下载方法
建立新文件夹
path = './images/' + tieba_name
if not os.path.exists (path.decode('utf8' )):
os.makedirs(path.decode('utf8' ))
下载图片
for img_url in img_urls:
fname = img_url.split('/' )[-1 ]
print 'downloading...' + fname
urllib.urlretrieve(img_url, './mv/' + fname)
存文件方法
with open ('./ip.txt' ,'a+' ) as f:
for x in res:
f.write (x+'............. \n' )
存为csv文件
with open ('infos.csv' ,'w' ) as cwf:
spamwriter=csv.writer(cwf,dialect='excel' )
for i in range((count/4 )+1 ):
spamwriter.writerow(data[i])
json转换方法
json_string =json.dumps(s)
str =json.loads(json_string)
发邮件
import smtplib
from email.mime.text import MIMEText
def emailSet () :
'''
:param date: 新闻时间
:param classify: 新闻类别
:param content: 新闻内容
:return:
'''
msg_from='932787833@qq.com'
passwd='muricwqcbpohbeec'
msg_to='932787733@qq.com'
subject="微博更新通知"
contents= '您好,您关注的微博已更新'
msg = MIMEText(contents)
msg['Subject' ] = subject
msg['From' ] = msg_from
msg['To' ] = msg_to
try :
s = smtplib.SMTP_SSL("smtp.qq.com" ,465 )
s.login(msg_from,passwd)
s.sendmail(msg_from, msg_to, msg.as_string())
s.quit()
except smtplib.SMTPException,e:
print "发送失败"
emailSet()
一些函数
xpath
xml python 官方文档:http://lxml.de/index.html
from lxml import etree
xml = etree.HTML(html) #帮html转化为xml格式
xml.xpath('//div[@class="app"]') #书写xpath规则
contains() #模糊查询
res = html.xpath('//ul/li[contains(@title,"t2")]') #获取title中包含t2的
response.xpath('//tr[1]/td//text()[name(..)!="p"]')
获取里面的所有文本除了P标签的
data = response.xpath('//div[@class="bct fc05 fc11 nbw-blog ztag"]')
content = data.xpath('string(.)').extract()[0]
获取div里面不同标签的所有的值 //div[@id='zoom' ][string(.) ]
res = html.xpath('//ul/li[text()=1]')
//div[@class='p_bar' ]/a[@class='p_num' ][last() ]/@href
last()获取当前的最后一个标签
li[position()>1]
获取除了第一位之后的元素
li[position()=1] 只获取第一位元素
xpath的算数
//input[@name='MaxPage']/ @value * //input [@name ='PageNum' ]/@value - //input [@name ='PageNum' ]/@value div 2
可以乘 可以 减
空格 div 2 就是除以2
BeautifulSoup
from bs4 import BeautifulSoup
#创建 Beautiful Soup 对象
soup = BeautifulSoup(html)
#书写规则
1 res = soup.select ('div[class="app"]' )
2 res = soup.find_all()
3 查询出来的结果如果需要其属性可以通过
for x in res:
url = x.attrs['href' ] #获取网址
#或者 url = x.['href']
x.a['href' ] # 提取连接地址
x.a.get ('href' ) # 提取连接地址
4 # 按照属性查找
res = soup.find_all('p' ,attrs={'class' : 'story' })
5 #模糊查询
res = soup.select ('a[class*="sister"]' )
#其他方式
print soup.title
获取标签内容
html=
soup=BeautifulSoup(html,
print soup.div
print soup.title
打开文件获取内容
soup=BeautifulSoup(open ('a.html' ),'html.parser' )
print soup.prettify()
进程线程和协程的概念
多进程
适合多核cpu,适合计算密集型
多线程-(一个进程可以包含多个线程) 系统级别调度进程和线程
IO密集型:爬虫是典型的网络IO
协程:轻量级线程(单线程,所有程序切换全部由编码来完成) 异步IO非阻塞
yield --- 把函数转换成生成器(挂起函数)
greenlet genvet
进程 独立堆和栈 操作系统调控
线程 独立栈,共享堆 操作系统调控
协程 独立栈,共享堆 代码调控
可以提高性能,失去使用多CPU能力
多线程
http: //www.cnblogs .com /alan-babyblog/p/5447946. html
selenium
安装selenium
pip install -U selenium
如果使用没设置路径,需要手动添加
executable_path=r"C:\Users\Administrator\Desktop\phantomjs-2.1.1-windows\bin\phantomjs.exe" ,desired_capabilities=dcap
re
patterm = re.compile(r'' )
res - pattern.findall(html)
print res
查询和替换一个文本字符串
格式:sub (replacement, string [,count=0 ])(replacement是被替换成的文本,string 是需要被替换的文本,count是一个可选参数,指最大被替换的数量)
>>> import re
>>>p=re.compile(‘blue|white|red’)
>>>print(p.sub (‘colour’,
colour socks and colourshoes
>>>print(p.sub (‘colour’,
colour socks and redshoes
subn()方法执行的效果跟sub ()一样,不过它会返回一个二维数组,包括替换后的新的字符串和总共替换的数量
match和search的区别
re模块中match(pattern,string[,flags]) ,检查string的开头是否与pattern匹配。
re模块中research(pattern,string[,flags]) ,在string搜索pattern的第一个匹配值。
>>>print(re.match(‘super’, ‘superstition’) .span() )
(0, 5)
>>>print(re.match(‘super’, ‘insuperable’) )
None
>>>print(re.search(‘super’, ‘superstition’) .span() )
(0, 5)
>>>print(re.search(‘super’, ‘insuperable’) .span() )
(2, 7)
requests
查看网页是否畅通,下载图片视频
通过url下载图片和视频有时候下载失败,可以先通过判断在进行下载
response = requests.get (img_url)
if response.status_code == 200 :
print response.url
temp = open ('./duanzi/' +str(fname)+'.jpg' ,'wb' )
temp.write (response.content)
temp.close ()
装词云
pip install wordcloud- 1.3 .2 -cp27 -cp27m -win32 . whl
pip install Jieba
词云使用
from wordcloud import WordCloud
import jieba
import PIL
import matplotlib.pyplot as plt
import numpy as np
def wordcloudplot (txt) :
path='d:/jieba/msyh.ttf'
path=unicode(path, 'utf8' ).encode('gb18030' )
alice_mask = np.array(PIL.Image.open('d:/she.jpg' ))
wordcloud = WordCloud(font_path=path,
background_color="white" ,
margin=5 , width=1800 , height=800 ,mask=alice_mask,max_words=2000 ,max_font_size=60 ,random_state=42 )
wordcloud = wordcloud.generate(txt)
wordcloud.to_file('d:/she2.jpg' )
plt.imshow(wordcloud)
plt.axis("off" )
plt.show()
def main () :
a=[]
f=open(r'd:\she.txt' ,'r' ).read()
words=list(jieba.cut(f))
for word in words:
if len(word)>1 :
a.append(word)
txt=r' ' .join(a)
wordcloudplot(txt)
if __name__=='__main__' :
main()
反爬虫
##源码问题
###/html
慎用,因为爬取整个html比较浪费资源.
遇到的主要有一个页面,内有两个html标签,而我们一般都是默认一个页面都是只有一个html的标签的,所以说当初我爬就是3 个url,结果给我返回了6 个结果,其中url重复了1 遍,然后三条数据为正确,三条数据为空,这个在当时纠结了好久,惯性思维也没有想到那个方面,后面看源码才发现在最下面有一个 script 标签里面放了三行代码,赫然就是用html的标签,真的是惯性思维害死人.
###源码混乱
我喜欢用xpath和正则进行解析数据,所以一直使用的谷歌的xpath和F12工具来写规则,这样就有了一个坑,因为python爬虫爬取的是源码,如果源码和你用F12看到的顺序不一样那就尴尬了,有一次爬取一个网站的电话,然而一直抓取为空,在浏览器xpath就可以获取到,然后后面看了网站的源码,把那段源码复制过后才发现里面多了好几个标签,F12里面没有的,然后后面用 \\ 成功抓取.
###假数据
踩得坑多了,自然就习惯了.
有一次爬一个 代理网站,网站的规则倒是很好写,然后抓取到之后发现竟然数据不对,用的scrapy,查看下载的页面数据为正确,没搞懂这个问题.IP可以爬下,但端口号就是乱的.
###多重标签
套路
在你想要的信息里面插入多重标签,然后随便写上数据,标签设置Hidden,爬的时候你就苦逼了.
选好那些标签是真的,然后用 xpath 的 string (.) 或者
爬取图片上的文字
导入 base64
import base64
def base64decode (self, *args, **kwargs) :
data = kwargs.get("data" )
missing_padding = 4 - len(data) % 4
if missing_padding:
data += b'=' * missing_padding
return base64.b64decode(data)