第一次写爬虫

准备工作

http请求头概念

1、Accept :请求报头域,用于指定客户端可接受哪些类型的信息。
2、Accept-Language :指定客户端可接受的语言类型。
3、Accept-Encoding :指定客户端可接受的内容编码。
4、Host :用于指定请求资源的主机IP 和端口号,其内容为请求URL 的原始服务器或网关的位
置。从HTTP 1. l 版本开始,请求必须包含此内容。
5、Cookie :也常用复数形式Cookies ,这是网站为了辨别用户进行会话跟踪而存储在用户本地
的数据。它的主要功能是维持当前访问会话。例如,我们输入用户名和密码成功登录某个网
站后,服务器会用会话保存登录状态信息,后面我们每次刷新或请求该站点的其他页面时,
会发现都是登录状态,这就是Cookies 的功劳。Cookies 里有信息标识了我们所对应的服务器
的会话,每次浏览器在请求该站点的页面时,都会在请求头中加上Cookies 并将其发送给服
务器,服务器通过Cookies 识别出是我们自己,并且查出当前状态是登录状态,所以返回结
果就是登录之后才能看到的网页内容。
6、Referer :此内容用来标识这个请求是从哪个页面发过来的,服务器可以拿到这一信息并做相
应的处理,如做来源统计、防盗链处理等。
7、User-Agent :简称UA ,它是一个特殊的字符串头,可以使服务器识别客户使用的操作系统
及版本、浏览器及版本等信息。在做爬虫时加上此信息,可以伪装为浏览器;如果不加,很
可能会被识别州为爬虫。
8、Content-Type :也叫互联网媒体类型( Internet Media Type )或者MIME 类型,在HTTP 协议
消息头中,它用来表示具体请求中的媒体类型信息。例如, text/html 代表HTML 格式,
image/gif代表GIF 图片, app lication/json 代表JSON 类型,更多对应关系可以查看此对照表:
http://tool.oschina.net/commons

Python3.7官方文档 https://docs.python.org/3.7/whatsnew/3.7.html

编程规范

1、每个缩进层级使用4个空格

2、每行最多79个字符

3、顶层函数或类的定义之间空两行(特别容易漏,漏的话,是报E302 expected 2 blank lines, found 1)

4、采用ASCII或者UTF-8编码文件

5、每条import导入一个模块,导入放在代码顶端,导入顺序是先标准库,第三方库,本地库

6、 小括号,大括号,中括号之间的逗号没有额外的空格

7、类命名采用骆驼命名法,CamelCase;函数用小写字符

8、函数命名使用小写字符,例如xxx_xxx_xxx;用下划线开头定义私有的属性或方法,如_xxx
 

1、识别网站所用技术

pip install builtwith  # 用于识别网站使用技术

# 安装模块,识别网站技术 
# pip install builtwith
import builtwith

# 执行识别命令

print(builtwith.parse('http://example.webscraping.com'), '\n')

2、寻找网站所有者  PS暂时不知道这步的作用

# pip install python-whois
import whois
print(whois.whois('http://sanberd.com'),'\n')
print(whois.whois('http://example.webscraping.com'),'\n')

3、下载网页(抓取)

模拟GET请求和POST请求

# import urllib 这样引入 会报request未定义。。。。。。
import socket
import urllib.parse
import urllib.request
import urllib.error

# 模拟get请求
def download (url ):
    print('Downloading :',url)
    try :
        response = urllib.request.urlopen(url)
        print(type(response))
        # print(response.read().decode('utf-8'))
    except urllib.request.URLError as e :
        print('Download error :',e.reason)
        response = None
    return response

download('https://www.python.org')
# data = download('http://www.sanberd.com/')
# print(data)

# 模拟post请求
def downloadbydata(url):
    try:
        postdata = bytes(urllib.parse.urlencode({'word':'hello'}), encoding='utf-8')
        print(postdata)
        # 设置超时时间 0.1 秒
        response = urllib.request.urlopen(url, data=postdata,timeout=0.1)    
        print(response.read().decode('utf-8'))
    except urllib.request.URLError as e:
        if isinstance(e.reason, socket.timeout):
            print('TIME OUT')

downloadbydata('http://httpbin.org/post')

完整模拟请求

from urllib import request, parse
#伪装火狐浏览器 
# Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11
# 谷歌浏览器
# Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
url = 'http://httpbin.org/post'
header = {
    # 'User-Agent': 'Mozilla/4.0 (compatible;MSIE 5.5;Windows NT)',
    # 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)',
    'User-Agent': 'Mozilla/5.0 (X11; U; Linux i686)',
    'Host':'httpbin.org'
}
dict = {
    'name':'Germey'
}
data= bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=header, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

遇到的第一个坑,导入自定义模块,模块文件不在当前文件目录,

需要设置导入目录,设置 support.py与当前文件同一个目录

#!/usr/bin/python3
# 文件名: support.py
import sys
import os
# 设置自定义搜索路径
bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
# print(bp)
modpath = os.sep.join(bp + ['utils'])
# print(modpath)
sys.path.insert(0, modpath)
print(sys.path)

在需要导入自定义模块的文件里执行

#!/usr/bin/python3
# 文件名: pachong003.py
import urllib.request
import urllib.error
import support
import 自定义模块的文件名

这样就可以把自己写的模块统一放到一个文件夹里,然后按需要引入了。

不过,这样写会报 [flake8] 引入模块 imported but unused [F401] 语法错误,看的郁闷,

所以,我取消了 flake8使用。。。。。。第一次搞这个,能有结果就行。。。

"python.linting.flake8Enabled": false, //启用flake8,首先需要pip3 install 
#!/usr/bin/python3
# 文件名: pachong_dali.py
from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener

# 模拟设置代理
proxy_handler = ProxyHandler({'http': '127.0.0.1'})
opener = build_opener(proxy_handler)
try:
    response = opener.open('https://www.baidu.com')
    print(response.read().decode('utf-8'))
except URLError as e:
    print(e.reason)

下面一个完整样例,照着书敲了好一会,才调通,正则表达式伤不起啊,,

抓取猫眼网站源码

#!/usr/bin/python3
# 抓取猫眼电影网站
import json
import requests
from requests.exceptions import RequestException
import re
import time


# 取页面
def get_one_page(url):
    try:
        headers = {
            'User-Agent':
            'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, lik Gecko)Chrome/52.0.2743.116 Safari/537.36'
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None


# 取内容
# 取排名  <dd>.*?board-index.*?>(.*?)</i>
# 取图片  .*?data-src="(.*?)"
# 取名称  .*?name.*?a.*?>(.*?)</a>
# 取主演  .*?star.*?>(.*?)</p>
# 取发布时间  .*?releasetime.*?>(.*?)</p>
# 取评分  .*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>
def parse_one_page(html):
    pattern = re.compile(
        '<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',
        re.S)
    # pattern = re.compile(
    #     r'<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?</dd>', re.S)
    items = re.findall(pattern, html)
    # strip 删除字符串开始于末尾的空格
    for item in items:
        yield {
            'index': item[0],
            'image': item[1],
            'title': item[2].strip(),
            'actor': item[3].strip()[3:] if len(item[3]) > 3 else '',
            'time': item[4].strip()[5:] if len(item[4]) > 5 else '',
            'score': item[5].strip() + item[6].strip()
        }
    return items


def write_to_file(content):
    # 写文件 a 追加模式
    with open('result.txt', 'a', encoding='utf-8') as f:
        # print(type(json.dumps(content)))
        f.write(json.dumps(content, ensure_ascii=False) + '\n')
    # 读文件
    # with open('result.txt', 'r', encoding='utf-8') as f:
    #     f.readlines()


def main(offset):
    url = 'https://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        # print(item)
        # print(json.dumps(item, ensure_ascii=False) + '\n')
        write_to_file(item)


if __name__ == '__main__':
    for i in range(10):
        print('开始抓取 第' + str(i + 1) + '次,')
        main(offset=i * 10)
        print('抓取完成 歇3秒', '\n')
        time.sleep(3)

# if __name__ == '__main__':
#    print('程序自身在运行')
# else:
#    print('我来自另一模块')
# $ python using_name.py
# 程序自身在运行
# $ python
# >>> import using_name
# 我来自另一模块

 

转载于:https://my.oschina.net/qingqingdego/blog/3003597

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值