爬虫小记

2020-04-01  本文已影响0人  浪里_个郎

内容包含:
1,简略描述爬虫代码编写流程
2,对于动态页面的爬取
代码:
https://github.com/zackLangChina/JavaCrawler

一,爬虫代码编写流程

1.1,发送HTTP request,获取HTTP response

java:

    //使用OKHTTP发送request
    private static OkHttpClient client = new OkHttpClient();
    //返回html
    public static String get(String url) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }

python:

import requests

#返回HTTP
def getHTTPText(url):
    try:
        r = requests.get(url, timeout=10)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""

1.2,在HTTP源码中搜索我们需要的元素

CSS选择器、正则表达式匹配等方式查找
java:

        //JSOUP解析
        Document document = Jsoup.parse(mHtml);
        Elements elements = document
                .select("ul[class=feed-list-hits feed-list-index]")
                .select("li[class=feed-row-wide J_feed_za feed-haojia]");
        for (Element element : elements) {
          ...

python:

    //BeautifulSoup解析
    soup = BeautifulSoup(html, "html.parser")
    for li in soup.find_all(name="li", attrs={"class": "av-gallery-item"}):

1.3,数据本地存储

写CSV文件或写数据库

当然,实际应用中会遇见很多问题:
1,需要模拟按键等操作
2,需要获取异步数据XHR并解析
3,反爬机制

二,静态页面和Ajax页面

某一网址为 https://www.xxx.com/xxx?id=a&page=b&value=c 这样的网址,显性地将属性添加到主体的后面,那么对于这类网站,我们只需要修改request的url就能抓取到静态页面中的数据。
对于Ajax的网页,网页刷新时,浏览器的Url并不会改变,而是通过发送一个request,获取了页面上一部分数据的刷新。ajax请求可能获得的是一部分页面的html代码,也可能是json格式的表单数据,我们可以在F12的preview或response里查看具体获得的数据类型,做不同的处理。

2.1构建ajax页面的request

以企查查举例。进入某个公司信息的页面,查看知识产权-专利信息,我们点击专利信息的翻页按钮,浏览器地址栏的url是不变的。打开F12,查看XHR信息,可以在Headers中看到request和response:


XHR

同时,在XHR的Response中可以看到新打开页面的HTML代码:


ajax返回的页面代码
我们还可以在Headers的最下面看到我们点击翻页时,request中带了哪些信息:
请求时发送的信息

这个图里我们可以看出,request带的主要信息有:
unique / companyname / p / tab / box
还有一些空参数:zlpublicationyear / zlipclist / zlkindcode / zllegalstatus

对比了两个公司的XHR Headers:

公司A:
https://www.qcc.com/company_getinfos?unique=06396efe66551d4ac07ee8cb41b0e325&companyname=%E5%B9%BF%E4%B8%9C%E5%B9%BF%E4%BF%A1%E9%80%9A%E4%BF%A1%E6%9C%8D%E5%8A%A1%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8&p=2&tab=assets&box=zhuanli&zlpublicationyear=&zlipclist=&zlkindcode=&zllegalstatus=
公司B:
https://www.qcc.com/company_getinfos?unique=70991e4c3796c47dd9d9e634fec5def0&companyname=%E6%B5%99%E6%B1%9F%E5%8D%8E%E4%BB%AA%E7%94%B5%E5%AD%90%E8%82%A1%E4%BB%BD%E6%9C%89%E9%99%90%E5%85%AC%E5%8F%B8&p=2&tab=assets&box=zhuanli&zlpublicationyear=&zlipclist=&zlkindcode=&zllegalstatus=

可以通过参数的差异和页面信息分析出参数的含义:
unique:企查查中某个公司的主页地址。如打开某个公司,地址栏是:
https://www.qcc.com/firm_06396efe66551d4ac07ee8cb41b0e325.html
06396efe66551d4ac07ee8cb41b0e325就和上面的unique=06396efe66551d4ac07ee8cb41b0e325值对应上了
companyname:公司名称
p:网页的页数,于是只要更改该键的值,我们就可以实现对每一页进行爬取
tab:标签页,代表了知识产权页面
box:作为不同的表格的标识。这里的zhuanli特指专利信息表格

那么,我们就可以给出爬取企查查企业专利信息的代码流程了:
1,获取企业名称列表
2,进入企业页面
3,从静态页面中获取专利信息总共的页数,如下图,可以通过遍历div class="m-b"中的元素得知总共有多少页
4,构建request,获取response中的页面信息


步骤3,获取专利信息页码

用代码说明一些细节:

    private final String url = "https://www.qcc.com/company_getinfos";
    private final String KEY_UNIQUE = "unique";
    private final String KEY_COMPANY = "companyname";
    private final String KEY_P = "p";
    private final String KEY_TAB = "tab";
    private final String KEY_BOX = "box";
    private final String TAB_ASSERTS = "assets";
    private final String BOX_ZHUANLI = "zhuanli";
    private final String COOKIE = "xxx" //浏览器的cookie,QCC不登录不能查询
    //通过HttpUrl.Builder构建参数键值对,其实就是帮你拼接字符串
    HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
    urlBuilder.addQueryParameter(KEY_UNIQUE,"06396efe66551d4ac07ee8cb41b0e325");
    urlBuilder.addQueryParameter(KEY_COMPANY,"广东广信通信服务有限公司");
    urlBuilder.addQueryParameter(KEY_P,"1");
    urlBuilder.addQueryParameter(KEY_TAB,TAB_ASSERTS);
    urlBuilder.addQueryParameter(KEY_BOX,BOX_ZHUANLI);

    //发送请求,注意需要补充请求头
    Request request = new Request.Builder()
        .url(urlBuilder.build())
        .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36")
        .addHeader("Cookie", cookie)
        .addHeader("accept","text/html, */*; q=0.01")
        .addHeader("accept-encoding","gzip, deflate, br")
        .addHeader("accept-language","zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7")
        .addHeader("referer","https://www.qcc.com/firm_06396efe66551d4ac07ee8cb41b0e325.html")
        .addHeader("sec-fetch-dest","empty")
        .addHeader("sec-fetch-mode","cors")
        .addHeader("sec-fetch-site","same-origin")
        .addHeader("x-requested-with","XMLHttpRequest")
        .build();

    Response response = client.newCall(request).execute();
    //返回html
    return response.body().string();

如果不把header加全一些,会被禁止访问:


企查查反爬

但即便这样,reponse得到的是一堆乱码,不知道具体是什么。但至少说明这样是可以用来获取ajax动态网页数据的,达到了学习的目的。


response返回
上一篇下一篇

猜你喜欢

热点阅读