《用Python写网络爬虫》读书笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/okm6666/article/details/79158085

【builtwith】 pip install builtwith
分析网站使用的技术
import builtwith
builtwith.parse(url)

【whois】 pip install python-whois
通过WHOIS协议查询域名的注册者
import whois
whois.whois(‘baidu.com’)

【urllib】urllib2在python3中集成到urllib中
1.简单的读取网页信息
from urllb import request
resp = request.urlopen(url)
html = resp.read()

2.模拟真实的浏览器
from urllib.request import Request,urlopen
req = Request(url)
req.add_header(‘user_agent’,user_agent)
html = urlopen(req).read()

3.urllib.robotparser
解析robot.txt文件后确定用户代理是否允许访问网页
rp = urllib.robotparser.RobotFileParser()
rp.set_url(‘/.robot.txt’)
rp.read()
rp.can_fetch(user_agent,url)


#用户代理发送请求获取网页html代码,并通过设置参数进行迭代设置重试次数
def download(url, user_agent='wswp', num_retries=2):
    print('downloading:', url)
    headers = {'user_agent':user_agent}
    try:
        req = Request(url,headers=headers)
        html = urlopen(req).read()
    except HTTPError as e:
        print('download error:', e.reason)
        html = None
        if num_retries > 0:
            if hasattr(e, 'code') and 500 <= e.code < 600:
                return download(url, num_retries=num_retries - 1)
    return str(html)

#通过正则表达式匹配html获取url地址
def crawl_sitemap(url):
    sitemap = download(url)
    links = re.findall(r'/places/default/(view/.*?\d)', sitemap)
    print(links)

#有时可以通过遍历id进行url的遍历
import itertools

def search_by_id():
    max_errors = 5
    num_errors = 0
    for page in itertools.count(1):
        url = "http://example.webscraping.com/places/default/view/{}".format(page)
        html = download(url)
        if html is None:
            num_errors += 1
            if num_errors == max_errors:
                break
        else:
            num_errors = 0

缓存可设置文件或数据库,数据库时间较文件缓存时间更久,但是免去文件系统的各种限制。
在使用缓存时可以通过压缩减少空间占用。以mongodb为例,序列化数据后使用zlib进行压缩

AJAX 异步JavaScript和XML,通过XMLHttpRequest动态生成web应用内容
在书中通过遍历接口获取信息时,使用json.loads()时会报错,Expecting value: line 1 column 1 (char 0) when trying to decode JSON.
可以直接使用request.get(url).json()得到json字符串

url = 'http://example.webscraping.com/places/ajax/search.json?&search_term=A&page_size=10&page=0'
jstr = requests.get(url).json()
print(jstr['records'][0]['country'])

理想情况下,单就这个接口,可以设置搜索条件后一次查询匹配所有结果。如将.替代查询条件

with open('countries.csv','w') as file:
    writer = csv.writer(file)
    for record in jstr['records']:
        country = record['country']
        print(country)
        writer.writerow([country])

writer.writerow会将字符串分隔在单元格里,通过将其变为list,在一个单元格里显示。

对网页动态内容的两种解决方案,逆向工程与渲染动态网页。

对于表单交互,GET和POST方法
GET会将查询字符串添加到URL中
POST请求中,数据在请求体中发送,与URL保持分离。
表单中enctype属性用于设置数据提交的编码,
application/x-www-form-urlencoded为默认编码类型,所有非字母数字类型的字符串都需要转换为十六进制的ASCII值
multipart/form-data不会对输入进行编码,使用MIME协议将其作为多个部分进行发送。

requests需要cookie进行登录时,可以通过保存cookie进行操作,也可以通过session保持cookie。
session = requests.session()

Mechanize 实现自动化表单处理,不支持python3

加载验证码

#获取图片
def get_captcha(tree):
    img = tree.cssselect('div#recaptcha img')[0].get('src')
    img = img.partition(',')[-1]  #分割获取图片二进制数据
    binary_img = base64.b64decode(img) # 以base64编码格式解码
    img = Image.open(BytesIO(binary_img))
    img.save('captcha.png')
    return img

Tesseract安装(配置环境变量)
http://code.google.com/p/tesseract-ocr/wiki/ReadMe
pip install pytesseract
使用pytesseract提示文件不存在时,修改pytesseract.py
tesseract_cmd = r’C:\Program Files (x86)\Tesseract-OCR\tesseract.exe’

#获取验证码
def get_captcha(tree):
    img = tree.cssselect('div#recaptcha img')[0].get('src')
    img = img.partition(',')[-1]  # 分割获取图片二进制数据
    binary_img = base64.b64decode(img)  # 以base64编码格式解码
    img = Image.open(BytesIO(binary_img))
    img.save('captcha.png')
    gray = img.convert('L')  # 将图片调灰
    gray.save('captcha_gray.png')
    bw = gray.point(lambda x: 0 if x < 1 else 255, '1')  # 只选取黑色像素部分
    bw.save('captcha_thresholded.png')

    return pytesseract.image_to_string(bw)
#进行注册
def register(first_name,last_name,email,password):
    URL = 'http://example.webscraping.com/places/default/user/register?_next=/places/default/index'
    session = requests.Session()
    r = session.get(URL)
    tree = lxml.html.fromstring(r.text)

    datas = {}
    elements = tree.cssselect("form input")
    for e in elements:
        if e.get('name'):
            datas[e.get('name')] = e.get('value')
    datas['recaptcha_response_field'] = get_captcha(tree)
    datas['first_name'] = first_name
    datas['last_name'] = last_name
    datas['email'] = email
    datas['password'] = datas['password_two'] = password

    r = session.post(URL,data=datas)
    print(r.url)
    return '/user/register' not in r.url

【Scrapy】
安装:scrapy已经支持python3
当直接通过pip install scrapy出现错误时
可以通过https://www.lfd.uci.edu/~gohlke/pythonlibs/
下载需要的lxml,Twisted,Scrapy三个whl文件,再通过pip进行安装即可。
lxml-4.1.1-cp36-cp36m-win32
Twisted-17.9.0-cp36-cp36m-win32
Scrapy-1.4.0-py2.py3-none-any

命令行输入scrapy startproject [project],当新项目被成功创建时,表示安装成功。

出现问题:ModuleNotFoundError: No module named ‘win32api’
解决方法:pip install pypiwin32

items.py 定义待抓区域的模型
settings.py 定义如用户代理,爬取延时等一些设置
spides/: 目录下存储实际的爬虫代码

通过内置的crawl模板生成爬虫的模板
scrapy genspider < spidername> < url> –template=crawl
运行爬虫:scrapy crawl < spidername> -s LOG_LEVEL=ERROR
-s LOG_LEVEL=ERROR 输出Error级别的信息

在爬虫文件下
rules下规定爬取的范围,allowed,deny 参数为正则表达式形式

scrapy shell < url> 在Python解释器下给出结果状态,通过response检查可用的数据。
如 response.url ,response.status

scrapy 使用lxml抓取数据,因此可以使用lxml的css选择器,在parse_item()方法中使用。
response.css(< cssselect>).extract()

scrapy crawl < spidername> –output=< file>
定义管道输出为文件格式

scrapy crawl < spidername > JOBDIR=< file >
在JOBDIR目录下保存状态,在正常结束后(非两次ctrl+c)可以恢复运行

猜你喜欢

转载自blog.csdn.net/okm6666/article/details/79158085