爬虫准备
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)
基本
爬取一个网页
import urllib2
base_url = 'http://www.liaoxuefeng.com'
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)
第一个反爬虫
import urllib2
import random
base_url = 'http://www.xicidaili.com/'
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)
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()
下载方法
建立新文件夹
# 根据tiebaname建立贴吧文件夹
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)
xml.xpath('//div[@class="app"]')
contains()
res = html.xpath('//ul/li[contains(@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
soup = BeautifulSoup(html)
1 res = soup.select('div[class="app"]')
2 res = soup.find_all()
3 查询出来的结果如果需要其属性可以通过
for x in res:
url = x.attrs['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='<title>welcome to gloryroad</title><div>join gloryroad soon<\div>'
soup=BeautifulSoup(html,'html.parser')
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:
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’,'blue socks and red shoes’))
colour socks and colourshoes
>>>print(p.sub(‘colour’,'blue socks and red shoes’,count=1))
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的标签的,所以说当初我爬就是3个url,结果给我返回了6个结果,其中url重复了1遍,然后三条数据为正确,三条数据为空,这个在当时纠结了好久,惯性思维也没有想到那个方面,后面看源码才发现在最下面有一个 script 标签里面放了三行代码,赫然就是用html的标签,真的是惯性思维害死人.
#
我喜欢用xpath和正则进行解析数据,所以一直使用的谷歌的xpath和F12工具来写规则,这样就有了一个坑,因为python爬虫爬取的是源码,如果源码和你用F12看到的顺序不一样那就尴尬了,有一次爬取一个网站的电话,然而一直抓取为空,在浏览器xpath就可以获取到,然后后面看了网站的源码,把那段源码复制过后才发现里面多了好几个标签,F12里面没有的,然后后面用 \\ 成功抓取.
#
踩得坑多了,自然就习惯了.
有一次爬一个 代理网站,网站的规则倒是很好写,然后抓取到之后发现竟然数据不对,用的scrapy,查看下载的页面数据为正确,没搞懂这个问题.IP可以爬下,但端口号就是乱的.
#
套路
在你想要的信息里面插入多重标签,然后随便写上数据,标签设置Hidden,爬的时候你就苦逼了.
选好那些标签是真的,然后用 xpath 的 string(.) 或者 //text() 来获取,真的能写的很混乱的标签我还没遇到过,估计没人那么疯狂.
爬取图片上的文字
导入 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)