我正在尝试编写一个代码,用于从用户输入的网站获取html代码。我需要在不使用urllib或其他类似库的情况下编写它。
from socket import *
url = (input("Please enter url: "))
host=gethostbyname(url)
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((host,80))
clientSocket.send(("GET " + host + "HTTP/1.1\n\n").encode("UTF-8"))
file = clientSocket.recv(1024)
print("The html code: ", file.decode("UTF-8"))
clientSocket.close()
代码运行正常。但是,当我输入诸如“www.stackoverflow.com”之类的网站时,我收到了来自主持人的“错误请求”回复:
The html code: HTTP/1.1 400 Bad Request
Date: Wed, 23 Mar 2016 16:14:27 GMT
Content-Type: text/html
Content-Length: 177
Connection: close
Server: -nginx
CF-RAY: -
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare-nginx</center>
</body>
</html>
为了从服务器获取实际的html代码,正确的请求是什么?谢谢
答案 0 :(得分:1)
主机名不是网址。由于您使用package com.example.country;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.Toast;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Select extends AppCompatActivity {
ImageView flagChoiceView;
Spinner spinnerCountry;
ArrayAdapter<CharSequence> adapter;
public static Button next2;
//Declaring all objects of type Country
List<Country> countries = Arrays.asList(
new Country("Austria", R.drawable.austriaflag),
new Country("Belgium", R.drawable.belgiumflag),
new Country("Denmark", R.drawable.denmarkflag),
new Country("England", R.drawable.englandflag),
new Country("France", R.drawable.franceflag),
new Country("Germany", R.drawable.germanflag),
new Country("Ireland", R.drawable.irelandflag),
new Country("Italy", R.drawable.italyflag),
new Country("Luxembourg", R.drawable.luxembourgeflag),
new Country("Portugal", R.drawable.portugalflag),
new Country("Spain", R.drawable.spainflag),
new Country("Sweden", R.drawable.swedenflag),
new Country("Switzerland", R.drawable.switzerlandflag),
new Country("Wales", R.drawable.walesflag)
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
afterSecondClick();
//Setting protocols for entering values into the text field
final TextWatcher numberInput = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
try {
countries.get(spinnerCountry.getSelectedItemPosition()).setFrequency(Integer.parseInt(s.toString()));
} catch (NumberFormatException e) {
Toast.makeText(getParent(), s + " is not a number", Toast.LENGTH_SHORT).show();
}
}
@Override
public void afterTextChanged(Editable s) {
}
};
//Creating a listener for the input field
EditText inputFrequency = (EditText) findViewById(R.id.inputFrequency);
inputFrequency.addTextChangedListener(numberInput);
//sortFunction(countryList);
spinnerCountry = (Spinner) findViewById(R.id.dropdown);
adapter = ArrayAdapter.createFromResource(this, R.array.country_list, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerCountry.setAdapter(adapter);
spinnerCountry.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, final int position, long id) {
flagChoiceView = (ImageView) findViewById(R.id.flagChoice);
flagChoiceView.setImageResource(countries.get(position).getFlag());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
//Linking the second activity to the third with a button click
public void afterSecondClick() {
next2 = (Button) findViewById(R.id.button);
next2.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Collections.sort(countries, Country.sortByFrequency());
Intent proceedAgain = new Intent("com.example.Country.Results");
proceedAgain.putExtra("firstCountry", countries.get(countries.size() - 1).getName());
proceedAgain.putExtra("secondCountry", countries.get(countries.size() - 2).getName());
proceedAgain.putExtra("thirdCountry", countries.get(countries.size() - 3).getName());
proceedAgain.putExtra("firstFrequency", countries.get(countries.size() - 1).getFrequency());
proceedAgain.putExtra("secondFrequency", countries.get(countries.size() - 2).getFrequency());
proceedAgain.putExtra("thirdFrequency", countries.get(countries.size() - 3).getFrequency());
startActivity(proceedAgain);
EditText inputFrequency = (EditText) findViewById(R.id.inputFrequency);
inputFrequency.setText("");
}
}
);
}
//Declaring a new inner class known as Country
private static class Country {
private final String name;
private int frequency;
private final int flag;
public Country(String Name, int flag) {
this.name = Name;
this.frequency = 0;
this.flag = flag;
}
public void setFrequency(int freq) {
this.frequency = freq;
}
public int getFrequency() {
return frequency;
}
public String getName() {
return name;
}
public int getFlag() {
return flag;
}
public static Comparator<Country> sortByFrequency() {
return new Comparator<Country>() {
@Override
public int compare(Country lhs, Country rhs) {
return Integer.compare(lhs.getFrequency(), rhs.getFrequency());
}
};
}
}
,因此您的脚本似乎仅提示输入主机名。 gethostbyname()
请求期望查看其第一个参数的URI。您还需要使用换行符发送回车符,并且您需要两个终止GET请求。你应该这样:
GET
此外,如果您只想下载URL,请使用像clientSocket.send(("GET / HTTP/1.1\r\n\r\n").encode("UTF-8"))
这样的库来处理所有HTTP协议详细信息。例如:
urllib2
答案 1 :(得分:0)
你不是在说HTTP / 1.1,但是你在第一行就是这样说的。
首先,GET
之后的令牌必须是服务器上的绝对路径;因此从/
开始。
其次,HTTP / 1.1请求必须包含Host:
标头。
第三,您的简单客户端应该说Connection: close
,因为它不处理分块连接。
使用以下脚本可能会取得更大的成功:
from socket import *
host = gethostbyname('stackoverflow.com')
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((host,80))
clientSocket.send((
"GET / HTTP/1.1\r\n"
"Host: stackoverflow.com\r\n"
"Connection: close\r\n\r\n").encode('utf-8'))
file = clientSocket.recv(1024)
print("The html code: ", file.decode("UTF-8"))
clientSocket.close()