爬虫学习笔记
list
extend函数 将两个list连起来
整齐打印抓到的html页面:直接print re.text就行
str 替换函数,replace,替换字符串内容
list index()求 元素的下标
字符串中加数字: sd=’%s_%s’%(i,t)
. for (i1, i2) in zip(list1,list2): 同时遍历两个list.找class span中的内容 self.title.append(lable.split(“\”“)[1])
str.isalpha()判断是否是字母
str.isdigit()判断是否是数字 判断是否包含字母或者数字:re.search(‘[a-z]’,str)
jieba分词:
txt = open("bxj.txt", "r", encoding='utf-8').read() words = jieba.lcut(txt) # words全部截取 counts = {} for word in words: if len(word) == 1: continue else: counts[word] = counts.get(word, 0) + 1 sd=sorted(counts.items(),key=lambda asd:asd[1],reverse=True)
tuple 强制转换转list
sd=list(sd)
解析数据
Beautifulsoup
初始化
soup = BeautifulSoup(html, ‘html.parser’)
深层次查找标签
bs4可以通过find 或者find_all()返回后再次调用,find或者find_all()
然后,通过result[‘href’]得到href的标签
tag
有两个属性: name,attrs
找出所有链接
names=soup.find_all(‘a’,{‘class’:’headpic’})
for each in names:
# print(each)
href=each[‘href’]
print(href)bs4 find_all(‘td’)找出所有,其他也一样
找出 sd=message.find_all(‘td’,{“class”:”tWhite”})
提取信息 只有一条的情况下: sd[0].getText
a=each.find(‘a’) print(a.text)得到a 中间text的文件内容
a=each.find(‘a’) print(a[href])找到a标签中的href
tr=soup.find(attrs{‘id’:’places_area_row’}) 找出id 属性值为‘’ 的数据
bs 对象分为4大类 Tag NavigableString BeautifulSoup Comment
tag:有两个属性: attrs name name 打印出来 标签的类别 比如 span
tag.attrs: {‘class’: [‘f666’]}找出span中的属性
tag.text打印出标签内部的内容找到< li >中的文字,用.string方法
lxml
导入方式
import lxml.html//
tree=lxml.html.fromstring(html)
. td=tree.cssselect(‘tr# places_area__row > td.w2p_fw’)[0]
代表id,首先找到tr为places_area的元素,然后找到td类属性为w2p_fw的元素然后text_content得到内容
选择a内span 标签 : a span
title 属性为 home 的所有标签 a[title=home]
- 选择class=link 的所有f a.link
获得div标签下的所有class
div_class=tree.xpath(‘//div/@class’)
print(div_class)
xpath学习
page = etree.HTML(html.lower().decode(‘utf-8’))
定位html标签,相对路径,绝对路径
- 绝对
path.xpath(u”/html/body/p”) - 相对
path.xpath(“//p”) 找出所有的p标签
定位到“
World News only on this page
p = page.xpath(u”/html/body/p[@style=’font-size: 200%’]”)
用如@name, @id, @value, @href, @src, @class….
函数text 取出p中的文本
position 是节点的位置 li[position()=2]”表示取得第二个li节点
代表所有的节点,比如用”/html/body//span可以取出body下第二级的所有span,而不管它上一级是div还是p或是其它什么东东。
href 找出所有的a标签和内容
hrefs=page.xpath(u”//a”)
for href in hrefs:
print(href.attrib)
print(href.text)’
找出链接
print(href.get(‘href’))
position
hrefs=page.xpath(u”//a[position()=2]”)
找出所有href标签中的第二个
取不到的内容
用tail 属性
print (u.tail)
结束节点后面的内容
解析字符串
处理url
- urljoin from urlparse import url
urls.append(urljoin(“https://tieba.baidu.com/“,each.get(‘href’)))
返回response的url: response.geturl()
- str 的操作:info=”.join(info.split()) 去掉所有的空格和换行符
不换行输出 print(‘123123’, end=”)
plt.rcParams[‘font.sans-serif’] = [‘SimHei’] 解决中文乱
码问题- dic.get(‘fan’)==None dic[‘fan’]=1 dic检查元素是否存在 以及添加元素的方法
解析json
json.loads()
- 将json结构的str 转换为 python类型数据结构 dict类型
json.dumps()
- 将python 的数据结构 dict 转换为json结构的str
抓取知乎内容
抓取我的收藏:
li class=” “> a class=” “> 2
urlib 和urllib2学习
标准款
response=urllib2.open(‘http://python.org/‘)
html=response.read()
加上header 和数据
user_agent='Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Mobile Safari/537.36'
headers={'User-Agent':user_agent}
values={‘name’ : ‘Michael Foord’, ‘location’ : ‘Northampton’, ‘language’ : ‘Python’ }
headers={‘user_agent’:user_agent)
data=urllib.urlencode(values)
req=urllib2.request(‘http://python.org‘,data,headers)
response=urllib2.urlopen(req,)
html=response.read()
加上代理
proxy_handler=urllib2.ProxyHandler({“http”:”http://114.215.95.188:3128“})
opener=urllib2.build_opener(proxy_handler)
urllib2.install_opener(opener)
加上cookie
- 设置cookie cookie=cookielib.CookieJar()
- build一个opener opener=urlliib2.build_opener(urllib.HTTPCookieProcessor(cj))
- 使用opener打开构建的request请求
内容保存到本地
将html 写入txt
html=req.text
with open('zhihu_html.text','w') as opener:
opener.write(html)
dest_dir为本地地址
urllib.urlretrieve(url , dest_dir)
将url存在本地磁盘的方法
- 将抓取下来的网页按照域名保存为一个个文件夹,然后将域名后面的东西保存为文件地址
解决乱码
如果原始是GBK
html=unicode(html,’GBK’).encode(‘UTF-8’)
判断遍历的最大深度
最原始的网页深度为 1:
如果 抓取到的网页来自原始网页 被抓取的网页深度+1
如果一个url的深度大于最大深度 就不把他加在队列中
慢慢的 队列就空了,抓取停止了
也就是说 设置最大深度为4
最多再抓取三层的信息
项目总结 2018.4.19
算是第一个爬虫小项目: 先总结一下
开始:通过crawler 方法,传入基本信息
维护一个url队列
从最初的url抓取到的url 如果抓取过,就 添加在对列中, deepth+=1如果url在本地磁盘缓存中,html就从本地缓存中调用
否则进行下载,并且将下载的页面写入缓存- 解析:通过正则解析html 找到需要的url
一个html页面所有的url抓取完毕, 该html对应的url出队列
- 解析:通过正则解析html 找到需要的url
定时,在下载时,为了防止ip被封,写一个定时类,可以在每次下载时延缓一定的时间
当队列为空,所有的抓取完毕时,调用回调函数,将信息写在csv文件中(这是个缺点,如果网络中断,岂不是之前的信息都要gg)
在抓取完一个url后,将html 文件写入本地缓存
文件功能:
playground.py:程序的入口
Downloader.py:下载方法的实现
disk_cache.py:页面缓存的实现
待完善:
- 用芒果db来代替本地储存
- 对爬虫功能的增加,比如识破验证码,处理ajax请求
- csv文件那块还要再商议一下
- 如果能用代理的话,也不错
- 分布式定时任务框架rabbitMq 和celery学一下
Mongo DB的使用
概念
集合:
mogod -dbpath 是储存文档的地方,相当于mysql的表格
集合没有固定的结构,比较松散,但集合中的文档,一般都有相关性
当插入一个文档时,集合就会建立
document
为主键 |
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置 |
数据类型
ObjectId 类似唯一的主键
运行mongoDB
mongod
常用shell
show dbs
use db
dbname.system.* //查看数据库的所有信息
insert
WriteResult({ “nInserted” : 1 })
删除当前数据库
db.dropDatabase()
创建集合
db.createCollection(“runoob”)
显示所有集合
show collections
插入文档
以下文档可以存储在 MongoDB 的 runoob 数据库 的 col 集合中:
db.COLLECTION_NAME.insert(document)
db.col.insert({title: ‘MongoDB 教程’, description: ‘MongoDB 是一个 Nosql 数据库’, by: ‘菜鸟教程’, url: ‘http://www.runoob.com‘, tags: [‘mongodb’, ‘database’, ‘NoSQL’], likes: 100 })
终端连接服务器进入shell :mongo
查看集合中的文档
db.col.find()
db.collections.count() 查看表中的元素个数
python连接mongodb 放在local中
- 默认端口号27017
2.终端输入 mongo 进入sql命令行
mysql 为key-value 模式
mongodb 的配置文件
/usr/local/etc
文件默认路径:/usr/local/var/mongodb
修改了数据库路径
赋权: sudo chown id -u
/Users/fanjialiang2401/data/mongo/
查看mongodb 是否在运行
mongodb 正确退出方式:
mongo // 从linux命令行进入mongod命令行
use admin // 切换到管理员模式
db.shutdownServer() // 关闭mongodb服务
pymongo
shell
- show dbs
- use db
- db.webpage.find()找出collection为webpage的所有元素
- db.webpage.count()
. db.webpage.find() - 搜索所有的值
for item in table.find():
print(item)
- db.collection.createIndex( { name: -1 } )
7.db.myColl.find( { category: “cafe” } ) - db.myColl.createIndex(
{ score: 1, price: 1, category: 1 },
{ collation: { locale: “fr” } } ) - db.myColl.find( { score: 5, category: “cafe” } )
高端方法
selenium
def get_html():
driver=webdriver.Firefox()
html=driver.get('https://search.jd.com/search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&gp=2&cid2=653&cid3=655&ev=exbrand_%E4%B8%89%E6%98%9F%28SAMSUNG%29%5E&page=1&s=1&click=0')
time.sleep(3)
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
time.sleep(3)
html = driver.find_element_by_xpath("//*").get_attribute("outerHTML")
return html
python shell
- client=MongoClient(‘localhost’,27017)
db = client.primer
db.webpage.find()找出collection为webpage的所有元素
. tablename.remove({“name”: “mike”})- counts=table_name.count()
coll = db.dataset
删除数据库
client
查看表中有多少元素
counts=table_name.count()
print(‘总行数:%s’%counts)找到一条记录
cols=table_name.find_one()找特定的某一行
result=table_name.find({“name”:”fanjialiang”})
连接到对应的数据库
连接数据库名为primer
db = client.primer
连接名称为dataset的collctions
coll = db.dataset
db=conn.get_database('local')
colletion=db.collection_names()
查找
result=db.webpage.find({‘url’:url})//查找出来的是游标
- result=db.webpage.find_one({‘_id’:url})
result= ‘ads’
for i in result:
print(i)
将url设为id
db.webpage.update({‘_id’:url},{‘$set’:{‘html’:html}},upsert=True)
删除
tablename.remove({"name": "mike"})
- 插入
table_name.insert({“name”:’fanjialiang’,”age”:18})
ps aux | grep mongo 查看mongodb 然后kill掉
requests
请求格式
response=requests.get(url=self.begin_url,headers=self.headers,cookies=CookieJar)
下载文件:
url=http://flupy.org/data/flags/fr/fr.gif
iamge=request.get(url).content
open(‘a.gif,’wb’) as opener:
opener.write(image)
解析csv文件
file=open(‘csv/top-1m.csv.zip’,’r’)
with ZipFile(file) as zf:
csv_filename=zf.namelist()[0]
for _,website in csv.reader(zf.open(csv_filename)):
urls.append(‘http://’+website)
下载最受欢迎的网站
下载一千个网页:
- 如果国内访问不到,设置一个超时时间,返回url,添加在错误url list中
- 如果能访问到,加在mongo数据库中,并且为加入的url,创建一个index序号,作为主键
- 计算访问花费的总时间。
- 设置数据库名称
- 回调函数先不创建
代理项目
- 不断的从互联网上抓取代理
- 将抓取下来的代理写在csv中
- 将好的代理筛选出来,返回一个List
- 抓取其他网站时,采用从代理池中随机选择一个
百度贴吧项目
- 将title抓下来
将内容抓下来
然后打印title,和对应的内容
每打印一行,输出换行
2.将页数抓下来,维持一个队列,每次从队列中取url,如果没访问过加加在队列中,否则跳过。
- 将抓下来的内容存放在mongoDB中 起名NBA50大
抓取淘宝模特信息
在主页面把模特的href 抓下来,然后进入每个的个人页面href
进入网页后,抓取个人域名,在进入每个人的个人域名把照片抓取下来
在个人页面上,把个人信息抓取下来,储存为csv文件
身高, 三围 , 个人页面, 等等
项目流程
downloader类负责下载 不要scrapeCallback方法了
hrottle类负责 限制速度
scrapeCallback为回调类,在完成下载后调用回调类将消息写入硬盘
diskCache 类负责将抓取的内容写到硬盘中
Link_crawler为总的开始