爬虫的基础学习

这篇博客介绍了Python爬虫的基础知识,包括使用Fiddler进行抓包,爬取网页,下载管理和存储数据,使用XPath和BeautifulSoup解析HTML,理解进程线程和协程,以及应对反爬虫策略。还涉及了requests库的使用,创建词云以及从图片中提取文字。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



爬虫准备

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)  # data必须urlencode一下
    requeset = urllib2.Request(base_url,data=data) 
    #发的是post请求,data是urlencode以后的编码
    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)
  #把python字典友好的格式化输出 接受一个字典对象  indent 缩进空格

基本

爬取一个网页

#coding:utf8

import urllib2

base_url = 'http://www.liaoxuefeng.com'
request = urllib2.Request(base_url)
response = urllib2.urlopen(request,timeout=30)
print response.read()
查询爬取网页
#coding:utf8
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)  #构造request对象
    response = urllib2.urlopen(request)
    return response.read()

if __name__ == '__main__':
    key = raw_input('请输入查询关键字:')
    result = search(key)
    print result
爬取贴吧第几页到第几页
#coding:utf8
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
百度翻译
#coding:utf8
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)  # data必须urlencode一下
    requeset = urllib2.Request(base_url,data=data)  #发的是post请求,data是urlencode以后的编码
    response = urllib2.urlopen(requeset) #发起请求
    data_json = response.read()  # 读取响应体
    data = json.loads(data_json)  #把json转换成python字典
    # print json.dumps(data,indent=4,ensure_ascii=False) #把python字典友好的格式化输出 接受一个字典对象  indent 缩进空格
    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)
自己写的
#coding:utf8
import urllib
import urllib2
from urllib import quote


def search(key):
    base_url = 'https://fanyi.baidu.com/'

    # wz = urllib.urlencode(key)
    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()

下载方法

建立新文件夹

# 根据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)

发邮件

#coding:utf8
#发邮件
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]')
#获取li下值为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='<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://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’,'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)
       #判断码200位正常
       #print response.status_code, type(response.status_code)
       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

词云使用

#coding:utf8
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(.)  或者   //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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值